Warning, /sdk/rust-qt-binding-generator/src/rust.rs is written in an unsupported language. File is not indexed.
0001 //! `rust` is the module that generates the rust code for the binding
0002
0003 use configuration::*;
0004 use configuration_private::*;
0005 use std::io::{Result, Write};
0006 use util::{snake_case, write_if_different};
0007
0008 fn rust_type(p: &Property) -> String {
0009 if p.optional {
0010 return format!("Option<{}>", p.property_type.rust_type());
0011 }
0012 p.property_type.rust_type().to_string()
0013 }
0014
0015 fn rust_type_(p: &ItemProperty) -> String {
0016 if p.optional {
0017 return format!("Option<{}>", p.item_property_type.rust_type());
0018 }
0019 p.item_property_type.rust_type().to_string()
0020 }
0021
0022 fn rust_return_type(p: &Property) -> String {
0023 let mut type_: String = p.property_type.rust_type().to_string();
0024 if type_ == "String" {
0025 type_ = "str".to_string();
0026 }
0027 if type_ == "Vec<u8>" {
0028 type_ = "[u8]".to_string();
0029 }
0030 if p.property_type.is_complex() {
0031 type_ = "&".to_string() + &type_;
0032 }
0033 if p.optional {
0034 return "Option<".to_string() + &type_ + ">";
0035 }
0036 type_
0037 }
0038
0039 fn rust_return_type_(p: &ItemProperty) -> String {
0040 let mut type_: String = p.item_property_type.rust_type().to_string();
0041 if type_ == "String" && !p.rust_by_value {
0042 type_ = "str".to_string();
0043 }
0044 if type_ == "Vec<u8>" && !p.rust_by_value {
0045 type_ = "[u8]".to_string();
0046 }
0047 if p.item_property_type.is_complex() && !p.rust_by_value {
0048 type_ = "&".to_string() + &type_;
0049 }
0050 if p.optional {
0051 return "Option<".to_string() + &type_ + ">";
0052 }
0053 type_
0054 }
0055
0056 fn rust_c_type(p: &ItemProperty) -> String {
0057 if p.optional {
0058 return format!("COption<{}>", p.item_property_type.rust_type());
0059 }
0060 p.item_property_type.rust_type().to_string()
0061 }
0062
0063 fn rust_type_init(p: &Property) -> &str {
0064 if p.optional {
0065 return "None";
0066 }
0067 p.property_type.rust_type_init()
0068 }
0069
0070 fn r_constructor_args_decl(r: &mut Vec<u8>, name: &str, o: &Object, conf: &Config) -> Result<()> {
0071 write!(r, " {}: *mut {}QObject", snake_case(name), o.name)?;
0072 for (p_name, p) in &o.properties {
0073 if let Type::Object(object) = &p.property_type {
0074 writeln!(r, ",")?;
0075 r_constructor_args_decl(r, p_name, object, conf)?;
0076 } else {
0077 write!(
0078 r,
0079 ",\n {}_{}_changed: extern fn(*mut {}QObject)",
0080 snake_case(name),
0081 snake_case(p_name),
0082 o.name
0083 )?;
0084 }
0085 }
0086 if o.object_type == ObjectType::List {
0087 write!(
0088 r,
0089 ",\n {}_new_data_ready: extern fn(*mut {}QObject)",
0090 snake_case(name),
0091 o.name
0092 )?;
0093 } else if o.object_type == ObjectType::Tree {
0094 write!(
0095 r,
0096 ",\n {}_new_data_ready: extern fn(*mut {}QObject, index: COption<usize>)",
0097 snake_case(name),
0098 o.name
0099 )?;
0100 }
0101 if o.object_type != ObjectType::Object {
0102 let index_decl = if o.object_type == ObjectType::Tree {
0103 " index: COption<usize>,"
0104 } else {
0105 ""
0106 };
0107 let dest_decl = if o.object_type == ObjectType::Tree {
0108 " index: COption<usize>,"
0109 } else {
0110 ""
0111 };
0112 write!(
0113 r,
0114 ",
0115 {2}_layout_about_to_be_changed: extern fn(*mut {0}QObject),
0116 {2}_layout_changed: extern fn(*mut {0}QObject),
0117 {2}_data_changed: extern fn(*mut {0}QObject, usize, usize),
0118 {2}_begin_reset_model: extern fn(*mut {0}QObject),
0119 {2}_end_reset_model: extern fn(*mut {0}QObject),
0120 {2}_begin_insert_rows: extern fn(*mut {0}QObject,{1} usize, usize),
0121 {2}_end_insert_rows: extern fn(*mut {0}QObject),
0122 {2}_begin_move_rows: extern fn(*mut {0}QObject,{1} usize, usize,{3} usize),
0123 {2}_end_move_rows: extern fn(*mut {0}QObject),
0124 {2}_begin_remove_rows: extern fn(*mut {0}QObject,{1} usize, usize),
0125 {2}_end_remove_rows: extern fn(*mut {0}QObject)",
0126 o.name,
0127 index_decl,
0128 snake_case(name),
0129 dest_decl
0130 )?;
0131 }
0132 Ok(())
0133 }
0134
0135 fn r_constructor_args(r: &mut Vec<u8>, name: &str, o: &Object, conf: &Config) -> Result<()> {
0136 for (name, p) in &o.properties {
0137 if let Type::Object(object) = &p.property_type {
0138 r_constructor_args(r, name, object, conf)?;
0139 }
0140 }
0141 writeln!(
0142 r,
0143 " let {}_emit = {}Emitter {{
0144 qobject: Arc::new(AtomicPtr::new({0})),",
0145 snake_case(name),
0146 o.name
0147 )?;
0148 for (p_name, p) in &o.properties {
0149 if p.is_object() {
0150 continue;
0151 }
0152 writeln!(
0153 r,
0154 " {}_changed: {}_{0}_changed,",
0155 snake_case(p_name),
0156 snake_case(name)
0157 )?;
0158 }
0159 if o.object_type != ObjectType::Object {
0160 writeln!(
0161 r,
0162 " new_data_ready: {}_new_data_ready,",
0163 snake_case(name)
0164 )?;
0165 }
0166 let mut model = String::new();
0167 if o.object_type != ObjectType::Object {
0168 let type_ = if o.object_type == ObjectType::List {
0169 "List"
0170 } else {
0171 "Tree"
0172 };
0173 model.push_str(", model");
0174 writeln!(
0175 r,
0176 " }};
0177 let model = {}{} {{
0178 qobject: {},
0179 layout_about_to_be_changed: {2}_layout_about_to_be_changed,
0180 layout_changed: {2}_layout_changed,
0181 data_changed: {2}_data_changed,
0182 begin_reset_model: {2}_begin_reset_model,
0183 end_reset_model: {2}_end_reset_model,
0184 begin_insert_rows: {2}_begin_insert_rows,
0185 end_insert_rows: {2}_end_insert_rows,
0186 begin_move_rows: {2}_begin_move_rows,
0187 end_move_rows: {2}_end_move_rows,
0188 begin_remove_rows: {2}_begin_remove_rows,
0189 end_remove_rows: {2}_end_remove_rows,",
0190 o.name,
0191 type_,
0192 snake_case(name)
0193 )?;
0194 }
0195 write!(
0196 r,
0197 " }};\n let d_{} = {}::new({0}_emit{}",
0198 snake_case(name),
0199 o.name,
0200 model
0201 )?;
0202 for (name, p) in &o.properties {
0203 if p.is_object() {
0204 write!(r, ",\n d_{}", snake_case(name))?;
0205 }
0206 }
0207 writeln!(r, ");")
0208 }
0209
0210 fn write_function(
0211 r: &mut Vec<u8>,
0212 (name, f): (&String, &Function),
0213 lcname: &str,
0214 o: &Object,
0215 ) -> Result<()> {
0216 let lc = snake_case(name);
0217 write!(
0218 r,
0219 "
0220 #[no_mangle]
0221 pub unsafe extern \"C\" fn {}_{}(ptr: *{} {}",
0222 lcname,
0223 lc,
0224 if f.mutable { "mut" } else { "const" },
0225 o.name
0226 )?;
0227 // write all the input arguments, for QString and QByteArray, write
0228 // pointers to their content and the length which is int in Qt
0229 for a in &f.arguments {
0230 write!(r, ", ")?;
0231 if a.argument_type.name() == "QString" {
0232 write!(r, "{}_str: *const c_ushort, {0}_len: c_int", a.name)?;
0233 } else if a.argument_type.name() == "QByteArray" {
0234 write!(r, "{}_str: *const c_char, {0}_len: c_int", a.name)?;
0235 } else {
0236 write!(r, "{}: {}", a.name, a.argument_type.rust_type())?;
0237 }
0238 }
0239 // If the return type is QString or QByteArray, append a pointer to the
0240 // variable that will be set to the argument list. Also add a setter
0241 // function.
0242 if f.return_type.is_complex() {
0243 writeln!(
0244 r,
0245 ", d: *mut {}, set: extern fn(*mut {0}, str: *const c_char, len: c_int)) {{",
0246 f.return_type.name()
0247 )?;
0248 } else if f.return_type == SimpleType::Void {
0249 writeln!(r, ") {{")?;
0250 } else {
0251 writeln!(r, ") -> {} {{", f.return_type.rust_type())?;
0252 }
0253 for a in &f.arguments {
0254 if a.argument_type.name() == "QString" {
0255 writeln!(
0256 r,
0257 " let mut {} = String::new();
0258 set_string_from_utf16(&mut {0}, {0}_str, {0}_len);",
0259 a.name
0260 )?;
0261 } else if a.argument_type.name() == "QByteArray" {
0262 writeln!(
0263 r,
0264 " let {} = {{ slice::from_raw_parts({0}_str as *const u8, to_usize({0}_len)) }};",
0265 a.name
0266 )?;
0267 }
0268 }
0269 if f.mutable {
0270 writeln!(r, " let o = &mut *ptr;")?;
0271 } else {
0272 writeln!(r, " let o = &*ptr;")?;
0273 }
0274 if f.return_type.is_complex() {
0275 write!(r, " let r = o.{}(", lc)?;
0276 } else {
0277 write!(r, " o.{}(", lc)?;
0278 }
0279 for (i, a) in f.arguments.iter().enumerate() {
0280 if i > 0 {
0281 write!(r, ", ")?;
0282 }
0283 write!(r, "{}", a.name)?;
0284 }
0285 write!(r, ")")?;
0286 if f.return_type.is_complex() {
0287 writeln!(r, ";")?;
0288 writeln!(
0289 r,
0290 " let s: *const c_char = r.as_ptr() as *const c_char;
0291 set(d, s, r.len() as i32);"
0292 )?;
0293 } else {
0294 writeln!(r)?;
0295 }
0296 writeln!(r, "}}")
0297 }
0298
0299 fn write_rust_interface_object(r: &mut Vec<u8>, o: &Object, conf: &Config) -> Result<()> {
0300 let lcname = snake_case(&o.name);
0301 writeln!(
0302 r,
0303 "
0304 pub struct {}QObject {{}}
0305
0306 pub struct {0}Emitter {{
0307 qobject: Arc<AtomicPtr<{0}QObject>>,",
0308 o.name
0309 )?;
0310 for (name, p) in &o.properties {
0311 if p.is_object() {
0312 continue;
0313 }
0314 writeln!(
0315 r,
0316 " {}_changed: extern fn(*mut {}QObject),",
0317 snake_case(name),
0318 o.name
0319 )?;
0320 }
0321
0322 if o.object_type == ObjectType::List {
0323 writeln!(r, " new_data_ready: extern fn(*mut {}QObject),", o.name)?;
0324 } else if o.object_type == ObjectType::Tree {
0325 writeln!(
0326 r,
0327 " new_data_ready: extern fn(*mut {}QObject, index: COption<usize>),",
0328 o.name
0329 )?;
0330 }
0331 writeln!(
0332 r,
0333 "}}
0334
0335 unsafe impl Send for {}Emitter {{}}
0336
0337 impl {0}Emitter {{
0338 /// Clone the emitter
0339 ///
0340 /// The emitter can only be cloned when it is mutable. The emitter calls
0341 /// into C++ code which may call into Rust again. If emmitting is possible
0342 /// from immutable structures, that might lead to access to a mutable
0343 /// reference. That is undefined behaviour and forbidden.
0344 pub fn clone(&mut self) -> {0}Emitter {{
0345 {0}Emitter {{
0346 qobject: self.qobject.clone(),",
0347 o.name
0348 )?;
0349 for (name, p) in &o.properties {
0350 if p.is_object() {
0351 continue;
0352 }
0353 writeln!(
0354 r,
0355 " {}_changed: self.{0}_changed,",
0356 snake_case(name),
0357 )?;
0358 }
0359 if o.object_type != ObjectType::Object {
0360 writeln!(r, " new_data_ready: self.new_data_ready,")?;
0361 }
0362 writeln!(
0363 r,
0364 " }}
0365 }}
0366 fn clear(&self) {{
0367 let n: *const {0}QObject = null();
0368 self.qobject.store(n as *mut {0}QObject, Ordering::SeqCst);
0369 }}",
0370 o.name
0371 )?;
0372
0373 for (name, p) in &o.properties {
0374 if p.is_object() {
0375 continue;
0376 }
0377 writeln!(
0378 r,
0379 " pub fn {}_changed(&mut self) {{
0380 let ptr = self.qobject.load(Ordering::SeqCst);
0381 if !ptr.is_null() {{
0382 (self.{0}_changed)(ptr);
0383 }}
0384 }}",
0385 snake_case(name)
0386 )?;
0387 }
0388
0389 for (name, f) in &o.functions {
0390 // Generate 'invoke_*' methods to call functions from the
0391 // event loop using QMetaObject::invokeMethod. Only
0392 // implemented for functions with no arguments and void return.
0393 if f.arguments.is_empty() && f.return_type == SimpleType::Void {
0394 writeln!(
0395 r,
0396 " /// Invoke the `{0}` function on the QObject's event loop.
0397 pub fn invoke_{0}(&mut self) {{
0398 let ptr = self.qobject.load(Ordering::SeqCst);
0399 if !ptr.is_null() {{
0400 unsafe {{
0401 qmetaobject__invokeMethod__0(
0402 ptr as *const std::ffi::c_void,
0403 std::ffi::CStr::from_bytes_with_nul_unchecked(b\"{0}\\0\").as_ptr()
0404 );
0405 }}
0406 }}
0407 }}",
0408 snake_case(name)
0409 )?;
0410 }
0411 }
0412
0413 if o.object_type == ObjectType::List {
0414 writeln!(
0415 r,
0416 " pub fn new_data_ready(&mut self) {{
0417 let ptr = self.qobject.load(Ordering::SeqCst);
0418 if !ptr.is_null() {{
0419 (self.new_data_ready)(ptr);
0420 }}
0421 }}"
0422 )?;
0423 } else if o.object_type == ObjectType::Tree {
0424 writeln!(
0425 r,
0426 " pub fn new_data_ready(&mut self, item: Option<usize>) {{
0427 let ptr = self.qobject.load(Ordering::SeqCst);
0428 if !ptr.is_null() {{
0429 (self.new_data_ready)(ptr, item.into());
0430 }}
0431 }}"
0432 )?;
0433 }
0434
0435 let mut model_struct = String::new();
0436 if o.object_type != ObjectType::Object {
0437 let type_ = if o.object_type == ObjectType::List {
0438 "List"
0439 } else {
0440 "Tree"
0441 };
0442 model_struct = format!(", model: {}{}", o.name, type_);
0443 let mut index = "";
0444 let mut index_decl = "";
0445 let mut index_c_decl = "";
0446 let mut dest = "";
0447 let mut dest_decl = "";
0448 let mut dest_c_decl = "";
0449 if o.object_type == ObjectType::Tree {
0450 index_decl = " index: Option<usize>,";
0451 index_c_decl = " index: COption<usize>,";
0452 index = " index.into(),";
0453 dest_decl = " dest: Option<usize>,";
0454 dest_c_decl = " dest: COption<usize>,";
0455 dest = " dest.into(),";
0456 }
0457 writeln!(
0458 r,
0459 "}}
0460
0461 #[derive(Clone)]
0462 pub struct {0}{1} {{
0463 qobject: *mut {0}QObject,
0464 layout_about_to_be_changed: extern fn(*mut {0}QObject),
0465 layout_changed: extern fn(*mut {0}QObject),
0466 data_changed: extern fn(*mut {0}QObject, usize, usize),
0467 begin_reset_model: extern fn(*mut {0}QObject),
0468 end_reset_model: extern fn(*mut {0}QObject),
0469 begin_insert_rows: extern fn(*mut {0}QObject,{4} usize, usize),
0470 end_insert_rows: extern fn(*mut {0}QObject),
0471 begin_move_rows: extern fn(*mut {0}QObject,{4} usize, usize,{7} usize),
0472 end_move_rows: extern fn(*mut {0}QObject),
0473 begin_remove_rows: extern fn(*mut {0}QObject,{4} usize, usize),
0474 end_remove_rows: extern fn(*mut {0}QObject),
0475 }}
0476
0477 impl {0}{1} {{
0478 pub fn layout_about_to_be_changed(&mut self) {{
0479 (self.layout_about_to_be_changed)(self.qobject);
0480 }}
0481 pub fn layout_changed(&mut self) {{
0482 (self.layout_changed)(self.qobject);
0483 }}
0484 pub fn data_changed(&mut self, first: usize, last: usize) {{
0485 (self.data_changed)(self.qobject, first, last);
0486 }}
0487 pub fn begin_reset_model(&mut self) {{
0488 (self.begin_reset_model)(self.qobject);
0489 }}
0490 pub fn end_reset_model(&mut self) {{
0491 (self.end_reset_model)(self.qobject);
0492 }}
0493 pub fn begin_insert_rows(&mut self,{2} first: usize, last: usize) {{
0494 (self.begin_insert_rows)(self.qobject,{3} first, last);
0495 }}
0496 pub fn end_insert_rows(&mut self) {{
0497 (self.end_insert_rows)(self.qobject);
0498 }}
0499 pub fn begin_move_rows(&mut self,{2} first: usize, last: usize,{5} destination: usize) {{
0500 (self.begin_move_rows)(self.qobject,{3} first, last,{6} destination);
0501 }}
0502 pub fn end_move_rows(&mut self) {{
0503 (self.end_move_rows)(self.qobject);
0504 }}
0505 pub fn begin_remove_rows(&mut self,{2} first: usize, last: usize) {{
0506 (self.begin_remove_rows)(self.qobject,{3} first, last);
0507 }}
0508 pub fn end_remove_rows(&mut self) {{
0509 (self.end_remove_rows)(self.qobject);
0510 }}",
0511 o.name, type_, index_decl, index, index_c_decl, dest_decl, dest, dest_c_decl
0512 )?;
0513 }
0514
0515 write!(
0516 r,
0517 "}}
0518
0519 pub trait {}Trait {{
0520 fn new(emit: {0}Emitter{}",
0521 o.name, model_struct
0522 )?;
0523 for (name, p) in &o.properties {
0524 if p.is_object() {
0525 write!(r, ",\n {}: {}", snake_case(name), p.type_name())?;
0526 }
0527 }
0528 writeln!(
0529 r,
0530 ") -> Self;
0531 fn emit(&mut self) -> &mut {}Emitter;",
0532 o.name
0533 )?;
0534 for (name, p) in &o.properties {
0535 let lc = snake_case(name).to_lowercase();
0536 if p.is_object() {
0537 writeln!(r, " fn {}(&self) -> &{};", lc, rust_type(p))?;
0538 writeln!(r, " fn {}_mut(&mut self) -> &mut {};", lc, rust_type(p))?;
0539 } else {
0540 if p.rust_by_function {
0541 write!(
0542 r,
0543 " fn {}<F>(&self, getter: F) where F: FnOnce({});",
0544 lc,
0545 rust_return_type(p)
0546 )?;
0547 } else {
0548 writeln!(r, " fn {}(&self) -> {};", lc, rust_return_type(p))?;
0549 }
0550 if p.write {
0551 if p.type_name() == "QByteArray" {
0552 if p.optional {
0553 writeln!(r, " fn set_{}(&mut self, value: Option<&[u8]>);", lc)?;
0554 } else {
0555 writeln!(r, " fn set_{}(&mut self, value: &[u8]);", lc)?;
0556 }
0557 } else {
0558 writeln!(r, " fn set_{}(&mut self, value: {});", lc, rust_type(p))?;
0559 }
0560 }
0561 }
0562 }
0563 for (name, f) in &o.functions {
0564 let lc = snake_case(name);
0565 let mut arg_list = String::new();
0566 if !f.arguments.is_empty() {
0567 for a in &f.arguments {
0568 let t = if a.argument_type.name() == "QByteArray" {
0569 "&[u8]"
0570 } else {
0571 a.argument_type.rust_type()
0572 };
0573 arg_list.push_str(&format!(", {}: {}", a.name, t));
0574 }
0575 }
0576 writeln!(
0577 r,
0578 " fn {}(&{}self{}) -> {};",
0579 lc,
0580 if f.mutable { "mut " } else { "" },
0581 arg_list,
0582 f.return_type.rust_type()
0583 )?;
0584 }
0585 if o.object_type == ObjectType::List {
0586 writeln!(
0587 r,
0588 " fn row_count(&self) -> usize;
0589 fn insert_rows(&mut self, _row: usize, _count: usize) -> bool {{ false }}
0590 fn remove_rows(&mut self, _row: usize, _count: usize) -> bool {{ false }}
0591 fn can_fetch_more(&self) -> bool {{
0592 false
0593 }}
0594 fn fetch_more(&mut self) {{}}
0595 fn sort(&mut self, _: u8, _: SortOrder) {{}}"
0596 )?;
0597 } else if o.object_type == ObjectType::Tree {
0598 writeln!(
0599 r,
0600 " fn row_count(&self, _: Option<usize>) -> usize;
0601 fn can_fetch_more(&self, _: Option<usize>) -> bool {{
0602 false
0603 }}
0604 fn fetch_more(&mut self, _: Option<usize>) {{}}
0605 fn sort(&mut self, _: u8, _: SortOrder) {{}}
0606 fn check_row(&self, index: usize, row: usize) -> Option<usize>;
0607 fn index(&self, item: Option<usize>, row: usize) -> usize;
0608 fn parent(&self, index: usize) -> Option<usize>;
0609 fn row(&self, index: usize) -> usize;"
0610 )?;
0611 }
0612 if o.object_type != ObjectType::Object {
0613 for (name, ip) in &o.item_properties {
0614 let name = snake_case(name);
0615 writeln!(
0616 r,
0617 " fn {}(&self, index: usize) -> {};",
0618 name,
0619 rust_return_type_(ip)
0620 )?;
0621 if ip.write {
0622 if ip.item_property_type.name() == "QByteArray" {
0623 if ip.optional {
0624 writeln!(
0625 r,
0626 " fn set_{}(&mut self, index: usize, _: Option<&[u8]>) -> bool;",
0627 name
0628 )?;
0629 } else {
0630 writeln!(
0631 r,
0632 " fn set_{}(&mut self, index: usize, _: &[u8]) -> bool;",
0633 name
0634 )?;
0635 }
0636 } else {
0637 writeln!(
0638 r,
0639 " fn set_{}(&mut self, index: usize, _: {}) -> bool;",
0640 name,
0641 rust_type_(ip)
0642 )?;
0643 }
0644 }
0645 }
0646 }
0647 writeln!(
0648 r,
0649 "}}
0650
0651 #[no_mangle]
0652 pub extern \"C\" fn {}_new(",
0653 lcname
0654 )?;
0655 r_constructor_args_decl(r, &lcname, o, conf)?;
0656 writeln!(r, ",\n) -> *mut {} {{", o.name)?;
0657 r_constructor_args(r, &lcname, o, conf)?;
0658 writeln!(
0659 r,
0660 " Box::into_raw(Box::new(d_{}))
0661 }}
0662
0663 #[no_mangle]
0664 pub unsafe extern \"C\" fn {0}_free(ptr: *mut {}) {{
0665 Box::from_raw(ptr).emit().clear();
0666 }}",
0667 lcname, o.name
0668 )?;
0669
0670 for (name, p) in &o.properties {
0671 let base = format!("{}_{}", lcname, snake_case(name));
0672 if p.is_object() {
0673 writeln!(
0674 r,
0675 "
0676 #[no_mangle]
0677 pub unsafe extern \"C\" fn {}_get(ptr: *mut {}) -> *mut {} {{
0678 (&mut *ptr).{}_mut()
0679 }}",
0680 base,
0681 o.name,
0682 rust_type(p),
0683 snake_case(name)
0684 )?;
0685 } else if p.is_complex() && !p.optional {
0686 if p.rust_by_function {
0687 writeln!(
0688 r,
0689 "
0690 #[no_mangle]
0691 pub unsafe extern \"C\" fn {}_get(
0692 ptr: *const {},
0693 p: *mut {},
0694 set: extern fn(*mut {2}, *const c_char, c_int),
0695 ) {{
0696 let o = &*ptr;
0697 o.{}(|v| {{
0698 let s: *const c_char = v.as_ptr() as *const c_char;
0699 set(p, s, to_c_int(v.len()));
0700 }});
0701 }}",
0702 base,
0703 o.name,
0704 p.type_name(),
0705 snake_case(name)
0706 )?;
0707 } else {
0708 writeln!(
0709 r,
0710 "
0711 #[no_mangle]
0712 pub unsafe extern \"C\" fn {}_get(
0713 ptr: *const {},
0714 p: *mut {},
0715 set: extern fn(*mut {2}, *const c_char, c_int),
0716 ) {{
0717 let o = &*ptr;
0718 let v = o.{}();
0719 let s: *const c_char = v.as_ptr() as *const c_char;
0720 set(p, s, to_c_int(v.len()));
0721 }}",
0722 base,
0723 o.name,
0724 p.type_name(),
0725 snake_case(name)
0726 )?;
0727 }
0728 if p.write && p.type_name() == "QString" {
0729 writeln!(
0730 r,
0731 "
0732 #[no_mangle]
0733 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_ushort, len: c_int) {{
0734 let o = &mut *ptr;
0735 let mut s = String::new();
0736 set_string_from_utf16(&mut s, v, len);
0737 o.set_{}(s);
0738 }}",
0739 base,
0740 o.name,
0741 snake_case(name)
0742 )?;
0743 } else if p.write {
0744 writeln!(
0745 r,
0746 "
0747 #[no_mangle]
0748 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_char, len: c_int) {{
0749 let o = &mut *ptr;
0750 let v = slice::from_raw_parts(v as *const u8, to_usize(len));
0751 o.set_{}(v);
0752 }}",
0753 base,
0754 o.name,
0755 snake_case(name)
0756 )?;
0757 }
0758 } else if p.is_complex() {
0759 writeln!(
0760 r,
0761 "
0762 #[no_mangle]
0763 pub unsafe extern \"C\" fn {}_get(
0764 ptr: *const {},
0765 p: *mut {},
0766 set: extern fn(*mut {2}, *const c_char, c_int),
0767 ) {{
0768 let o = &*ptr;
0769 let v = o.{}();
0770 if let Some(v) = v {{
0771 let s: *const c_char = v.as_ptr() as *const c_char;
0772 set(p, s, to_c_int(v.len()));
0773 }}
0774 }}",
0775 base,
0776 o.name,
0777 p.type_name(),
0778 snake_case(name)
0779 )?;
0780 if p.write && p.type_name() == "QString" {
0781 writeln!(
0782 r,
0783 "
0784 #[no_mangle]
0785 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_ushort, len: c_int) {{
0786 let o = &mut *ptr;
0787 let mut s = String::new();
0788 set_string_from_utf16(&mut s, v, len);
0789 o.set_{}(Some(s));
0790 }}",
0791 base,
0792 o.name,
0793 snake_case(name)
0794 )?;
0795 } else if p.write {
0796 writeln!(
0797 r,
0798 "
0799 #[no_mangle]
0800 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_char, len: c_int) {{
0801 let o = &mut *ptr;
0802 let v = slice::from_raw_parts(v as *const u8, to_usize(len));
0803 o.set_{}(Some(v.into()));
0804 }}",
0805 base,
0806 o.name,
0807 snake_case(name)
0808 )?;
0809 }
0810 } else if p.optional {
0811 writeln!(
0812 r,
0813 "
0814 #[no_mangle]
0815 pub unsafe extern \"C\" fn {}_get(ptr: *const {}) -> COption<{}> {{
0816 match (&*ptr).{}() {{
0817 Some(value) => COption {{ data: value, some: true }},
0818 None => COption {{ data: {2}::default(), some: false}}
0819 }}
0820 }}",
0821 base,
0822 o.name,
0823 p.property_type.rust_type(),
0824 snake_case(name)
0825 )?;
0826 if p.write {
0827 writeln!(
0828 r,
0829 "
0830 #[no_mangle]
0831 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: {}) {{
0832 (&mut *ptr).set_{}(Some(v));
0833 }}",
0834 base,
0835 o.name,
0836 p.property_type.rust_type(),
0837 snake_case(name)
0838 )?;
0839 }
0840 } else {
0841 writeln!(
0842 r,
0843 "
0844 #[no_mangle]
0845 pub unsafe extern \"C\" fn {}_get(ptr: *const {}) -> {} {{
0846 (&*ptr).{}()
0847 }}",
0848 base,
0849 o.name,
0850 rust_type(p),
0851 snake_case(name)
0852 )?;
0853 if p.write {
0854 writeln!(
0855 r,
0856 "
0857 #[no_mangle]
0858 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: {}) {{
0859 (&mut *ptr).set_{}(v);
0860 }}",
0861 base,
0862 o.name,
0863 rust_type(p),
0864 snake_case(name)
0865 )?;
0866 }
0867 }
0868 if p.write && p.optional {
0869 writeln!(
0870 r,
0871 "
0872 #[no_mangle]
0873 pub unsafe extern \"C\" fn {}_set_none(ptr: *mut {}) {{
0874 let o = &mut *ptr;
0875 o.set_{}(None);
0876 }}",
0877 base,
0878 o.name,
0879 snake_case(name)
0880 )?;
0881 }
0882 }
0883 for f in &o.functions {
0884 write_function(r, f, &lcname, o)?;
0885 }
0886 if o.object_type == ObjectType::List {
0887 writeln!(
0888 r,
0889 "
0890 #[no_mangle]
0891 pub unsafe extern \"C\" fn {1}_row_count(ptr: *const {0}) -> c_int {{
0892 to_c_int((&*ptr).row_count())
0893 }}
0894 #[no_mangle]
0895 pub unsafe extern \"C\" fn {1}_insert_rows(ptr: *mut {0}, row: c_int, count: c_int) -> bool {{
0896 (&mut *ptr).insert_rows(to_usize(row), to_usize(count))
0897 }}
0898 #[no_mangle]
0899 pub unsafe extern \"C\" fn {1}_remove_rows(ptr: *mut {0}, row: c_int, count: c_int) -> bool {{
0900 (&mut *ptr).remove_rows(to_usize(row), to_usize(count))
0901 }}
0902 #[no_mangle]
0903 pub unsafe extern \"C\" fn {1}_can_fetch_more(ptr: *const {0}) -> bool {{
0904 (&*ptr).can_fetch_more()
0905 }}
0906 #[no_mangle]
0907 pub unsafe extern \"C\" fn {1}_fetch_more(ptr: *mut {0}) {{
0908 (&mut *ptr).fetch_more()
0909 }}
0910 #[no_mangle]
0911 pub unsafe extern \"C\" fn {1}_sort(
0912 ptr: *mut {0},
0913 column: u8,
0914 order: SortOrder,
0915 ) {{
0916 (&mut *ptr).sort(column, order)
0917 }}",
0918 o.name, lcname
0919 )?;
0920 } else if o.object_type == ObjectType::Tree {
0921 writeln!(
0922 r,
0923 "
0924 #[no_mangle]
0925 pub unsafe extern \"C\" fn {1}_row_count(
0926 ptr: *const {0},
0927 index: COption<usize>,
0928 ) -> c_int {{
0929 to_c_int((&*ptr).row_count(index.into()))
0930 }}
0931 #[no_mangle]
0932 pub unsafe extern \"C\" fn {1}_can_fetch_more(
0933 ptr: *const {0},
0934 index: COption<usize>,
0935 ) -> bool {{
0936 (&*ptr).can_fetch_more(index.into())
0937 }}
0938 #[no_mangle]
0939 pub unsafe extern \"C\" fn {1}_fetch_more(ptr: *mut {0}, index: COption<usize>) {{
0940 (&mut *ptr).fetch_more(index.into())
0941 }}
0942 #[no_mangle]
0943 pub unsafe extern \"C\" fn {1}_sort(
0944 ptr: *mut {0},
0945 column: u8,
0946 order: SortOrder
0947 ) {{
0948 (&mut *ptr).sort(column, order)
0949 }}
0950 #[no_mangle]
0951 pub unsafe extern \"C\" fn {1}_check_row(
0952 ptr: *const {0},
0953 index: usize,
0954 row: c_int,
0955 ) -> COption<usize> {{
0956 (&*ptr).check_row(index, to_usize(row)).into()
0957 }}
0958 #[no_mangle]
0959 pub unsafe extern \"C\" fn {1}_index(
0960 ptr: *const {0},
0961 index: COption<usize>,
0962 row: c_int,
0963 ) -> usize {{
0964 (&*ptr).index(index.into(), to_usize(row))
0965 }}
0966 #[no_mangle]
0967 pub unsafe extern \"C\" fn {1}_parent(ptr: *const {0}, index: usize) -> QModelIndex {{
0968 if let Some(parent) = (&*ptr).parent(index) {{
0969 QModelIndex {{
0970 row: to_c_int((&*ptr).row(parent)),
0971 internal_id: parent,
0972 }}
0973 }} else {{
0974 QModelIndex {{
0975 row: -1,
0976 internal_id: 0,
0977 }}
0978 }}
0979 }}
0980 #[no_mangle]
0981 pub unsafe extern \"C\" fn {1}_row(ptr: *const {0}, index: usize) -> c_int {{
0982 to_c_int((&*ptr).row(index))
0983 }}",
0984 o.name, lcname
0985 )?;
0986 }
0987 if o.object_type != ObjectType::Object {
0988 let (index_decl, index) = if o.object_type == ObjectType::Tree {
0989 (", index: usize", "index")
0990 } else {
0991 (", row: c_int", "to_usize(row)")
0992 };
0993 for (name, ip) in &o.item_properties {
0994 if ip.is_complex() && !ip.optional {
0995 writeln!(
0996 r,
0997 "
0998 #[no_mangle]
0999 pub unsafe extern \"C\" fn {}_data_{}(
1000 ptr: *const {}{},
1001 d: *mut {},
1002 set: extern fn(*mut {4}, *const c_char, len: c_int),
1003 ) {{
1004 let o = &*ptr;
1005 let data = o.{1}({});
1006 let s: *const c_char = data.as_ptr() as *const c_char;
1007 set(d, s, to_c_int(data.len()));
1008 }}",
1009 lcname,
1010 snake_case(name),
1011 o.name,
1012 index_decl,
1013 ip.type_name(),
1014 index
1015 )?;
1016 } else if ip.is_complex() {
1017 writeln!(
1018 r,
1019 "
1020 #[no_mangle]
1021 pub unsafe extern \"C\" fn {}_data_{}(
1022 ptr: *const {}{},
1023 d: *mut {},
1024 set: extern fn(*mut {4}, *const c_char, len: c_int),
1025 ) {{
1026 let o = &*ptr;
1027 let data = o.{1}({});
1028 if let Some(data) = data {{
1029 let s: *const c_char = data.as_ptr() as *const c_char;
1030 set(d, s, to_c_int(data.len()));
1031 }}
1032 }}",
1033 lcname,
1034 snake_case(name),
1035 o.name,
1036 index_decl,
1037 ip.type_name(),
1038 index
1039 )?;
1040 } else {
1041 writeln!(
1042 r,
1043 "
1044 #[no_mangle]
1045 pub unsafe extern \"C\" fn {}_data_{}(ptr: *const {}{}) -> {} {{
1046 let o = &*ptr;
1047 o.{1}({}){}
1048 }}",
1049 lcname,
1050 snake_case(name),
1051 o.name,
1052 index_decl,
1053 rust_c_type(ip),
1054 index,
1055 if ip.optional { ".into()" } else { "" }
1056 )?;
1057 }
1058 if ip.write {
1059 let val = if ip.optional { "Some(v)" } else { "v" };
1060 if ip.type_name() == "QString" {
1061 writeln!(
1062 r,
1063 "
1064 #[no_mangle]
1065 pub unsafe extern \"C\" fn {}_set_data_{}(
1066 ptr: *mut {}{},
1067 s: *const c_ushort, len: c_int,
1068 ) -> bool {{
1069 let o = &mut *ptr;
1070 let mut v = String::new();
1071 set_string_from_utf16(&mut v, s, len);
1072 o.set_{1}({}, {})
1073 }}",
1074 lcname,
1075 snake_case(name),
1076 o.name,
1077 index_decl,
1078 index,
1079 val
1080 )?;
1081 } else if ip.type_name() == "QByteArray" {
1082 writeln!(
1083 r,
1084 "
1085 #[no_mangle]
1086 pub unsafe extern \"C\" fn {}_set_data_{}(
1087 ptr: *mut {}{},
1088 s: *const c_char, len: c_int,
1089 ) -> bool {{
1090 let o = &mut *ptr;
1091 let slice = ::std::slice::from_raw_parts(s as *const u8, to_usize(len));
1092 o.set_{1}({}, {})
1093 }}",
1094 lcname,
1095 snake_case(name),
1096 o.name,
1097 index_decl,
1098 index,
1099 if ip.optional { "Some(slice)" } else { "slice" }
1100 )?;
1101 } else {
1102 let type_ = ip.item_property_type.rust_type();
1103 writeln!(
1104 r,
1105 "
1106 #[no_mangle]
1107 pub unsafe extern \"C\" fn {}_set_data_{}(
1108 ptr: *mut {}{},
1109 v: {},
1110 ) -> bool {{
1111 (&mut *ptr).set_{1}({}, {})
1112 }}",
1113 lcname,
1114 snake_case(name),
1115 o.name,
1116 index_decl,
1117 type_,
1118 index,
1119 val
1120 )?;
1121 }
1122 }
1123 if ip.write && ip.optional {
1124 writeln!(
1125 r,
1126 "
1127 #[no_mangle]
1128 pub unsafe extern \"C\" fn {}_set_data_{}_none(ptr: *mut {}{}) -> bool {{
1129 (&mut *ptr).set_{1}({}, None)
1130 }}",
1131 lcname,
1132 snake_case(name),
1133 o.name,
1134 index_decl,
1135 index
1136 )?;
1137 }
1138 }
1139 }
1140 Ok(())
1141 }
1142
1143 fn write_rust_types(conf: &Config, r: &mut Vec<u8>) -> Result<()> {
1144 let mut has_option = false;
1145 let mut has_string = false;
1146 let mut has_byte_array = false;
1147 let mut has_list_or_tree = false;
1148
1149 for o in conf.objects.values() {
1150 has_list_or_tree |= o.object_type != ObjectType::Object;
1151 for p in o.properties.values() {
1152 has_option |= p.optional;
1153 has_string |= p.property_type == Type::Simple(SimpleType::QString);
1154 has_byte_array |= p.property_type == Type::Simple(SimpleType::QByteArray);
1155 }
1156 for p in o.item_properties.values() {
1157 has_option |= p.optional;
1158 has_string |= p.item_property_type == SimpleType::QString;
1159 has_byte_array |= p.item_property_type == SimpleType::QByteArray;
1160 }
1161 for f in o.functions.values() {
1162 has_string |= f.return_type == SimpleType::QString;
1163 has_byte_array |= f.return_type == SimpleType::QByteArray;
1164 for a in &f.arguments {
1165 has_string |= a.argument_type == SimpleType::QString;
1166 has_byte_array |= a.argument_type == SimpleType::QByteArray;
1167 }
1168 }
1169 }
1170
1171 if has_option || has_list_or_tree {
1172 writeln!(
1173 r,
1174 "
1175
1176 #[repr(C)]
1177 pub struct COption<T> {{
1178 data: T,
1179 some: bool,
1180 }}
1181
1182 impl<T> COption<T> {{
1183 #![allow(dead_code)]
1184 fn into(self) -> Option<T> {{
1185 if self.some {{
1186 Some(self.data)
1187 }} else {{
1188 None
1189 }}
1190 }}
1191 }}
1192
1193 impl<T> From<Option<T>> for COption<T>
1194 where
1195 T: Default,
1196 {{
1197 fn from(t: Option<T>) -> COption<T> {{
1198 if let Some(v) = t {{
1199 COption {{
1200 data: v,
1201 some: true,
1202 }}
1203 }} else {{
1204 COption {{
1205 data: T::default(),
1206 some: false,
1207 }}
1208 }}
1209 }}
1210 }}"
1211 )?;
1212 }
1213 if has_string {
1214 writeln!(
1215 r,
1216 "
1217
1218 pub enum QString {{}}
1219
1220 fn set_string_from_utf16(s: &mut String, str: *const c_ushort, len: c_int) {{
1221 let utf16 = unsafe {{ slice::from_raw_parts(str, to_usize(len)) }};
1222 let characters = decode_utf16(utf16.iter().cloned())
1223 .map(|r| r.unwrap());
1224 s.clear();
1225 s.extend(characters);
1226 }}
1227 "
1228 )?;
1229 }
1230 if has_byte_array {
1231 writeln!(
1232 r,
1233 "
1234
1235 pub enum QByteArray {{}}"
1236 )?;
1237 }
1238 if has_list_or_tree {
1239 writeln!(
1240 r,
1241 "
1242
1243 #[repr(C)]
1244 #[derive(PartialEq, Eq, Debug)]
1245 pub enum SortOrder {{
1246 Ascending = 0,
1247 Descending = 1,
1248 }}
1249
1250 #[repr(C)]
1251 pub struct QModelIndex {{
1252 row: c_int,
1253 internal_id: usize,
1254 }}"
1255 )?;
1256 }
1257
1258 if has_string || has_byte_array || has_list_or_tree {
1259 writeln!(
1260 r,
1261 "
1262
1263 fn to_usize(n: c_int) -> usize {{
1264 if n < 0 {{
1265 panic!(\"Cannot cast {{}} to usize\", n);
1266 }}
1267 n as usize
1268 }}
1269 "
1270 )?;
1271 }
1272
1273 if has_string || has_byte_array || has_list_or_tree {
1274 writeln!(
1275 r,
1276 "
1277 fn to_c_int(n: usize) -> c_int {{
1278 if n > c_int::max_value() as usize {{
1279 panic!(\"Cannot cast {{}} to c_int\", n);
1280 }}
1281 n as c_int
1282 }}
1283 "
1284 )?;
1285 }
1286 Ok(())
1287 }
1288
1289 pub fn write_interface(conf: &Config) -> Result<()> {
1290 let mut r = Vec::new();
1291 writeln!(
1292 r,
1293 "/* generated by rust_qt_binding_generator */
1294 use libc::{{c_char, c_ushort, c_int}};
1295 use std::slice;
1296 use std::char::decode_utf16;
1297
1298 use std::sync::Arc;
1299 use std::sync::atomic::{{AtomicPtr, Ordering}};
1300 use std::ptr::null;
1301
1302 use {}{}::*;",
1303 get_module_prefix(conf),
1304 conf.rust.implementation_module
1305 )?;
1306
1307 writeln!(
1308 r,
1309 "
1310 extern \"C\" {{
1311 pub fn qmetaobject__invokeMethod__0(obj: *const std::ffi::c_void, member: *const c_char);
1312 }}
1313 "
1314 )?;
1315
1316 write_rust_types(conf, &mut r)?;
1317
1318 for object in conf.objects.values() {
1319 write_rust_interface_object(&mut r, object, conf)?;
1320 }
1321 let mut file = conf
1322 .config_file
1323 .parent()
1324 .unwrap()
1325 .join(&conf.rust.dir)
1326 .join("src")
1327 .join(&conf.rust.interface_module);
1328 file.set_extension("rs");
1329 write_if_different(file, &r)
1330 }
1331
1332 fn write_rust_implementation_object(r: &mut Vec<u8>, o: &Object) -> Result<()> {
1333 if o.object_type != ObjectType::Object {
1334 writeln!(r, "#[derive(Default, Clone)]")?;
1335 writeln!(r, "struct {}Item {{", o.name)?;
1336 for (name, ip) in &o.item_properties {
1337 let lc = snake_case(name);
1338 if ip.optional {
1339 writeln!(
1340 r,
1341 " {}: Option<{}>,",
1342 lc,
1343 ip.item_property_type.rust_type()
1344 )?;
1345 } else {
1346 writeln!(r, " {}: {},", lc, ip.item_property_type.rust_type())?;
1347 }
1348 }
1349 writeln!(r, "}}\n")?;
1350 }
1351 let mut model_struct = String::new();
1352 writeln!(r, "pub struct {} {{\n emit: {0}Emitter,", o.name)?;
1353 if o.object_type == ObjectType::List {
1354 model_struct = format!(", model: {}List", o.name);
1355 writeln!(r, " model: {}List,", o.name)?;
1356 } else if o.object_type == ObjectType::Tree {
1357 model_struct = format!(", model: {}Tree", o.name);
1358 writeln!(r, " model: {}Tree,", o.name)?;
1359 }
1360 for (name, p) in &o.properties {
1361 let lc = snake_case(name);
1362 writeln!(r, " {}: {},", lc, rust_type(p))?;
1363 }
1364 if o.object_type != ObjectType::Object {
1365 writeln!(r, " list: Vec<{}Item>,", o.name)?;
1366 }
1367 writeln!(r, "}}\n")?;
1368 for (name, p) in &o.properties {
1369 if p.is_object() {
1370 model_struct += &format!(", {}: {}", name, p.type_name());
1371 }
1372 }
1373 writeln!(
1374 r,
1375 "impl {}Trait for {0} {{
1376 fn new(emit: {0}Emitter{}) -> {0} {{
1377 {0} {{
1378 emit,",
1379 o.name, model_struct
1380 )?;
1381 if o.object_type != ObjectType::Object {
1382 writeln!(r, " model,")?;
1383 writeln!(r, " list: Vec::new(),")?;
1384 }
1385 for (name, p) in &o.properties {
1386 let lc = snake_case(name);
1387 if p.is_object() {
1388 writeln!(r, " {},", lc)?;
1389 } else {
1390 writeln!(r, " {}: {},", lc, rust_type_init(p))?;
1391 }
1392 }
1393 writeln!(
1394 r,
1395 " }}
1396 }}
1397 fn emit(&mut self) -> &mut {}Emitter {{
1398 &self.emit
1399 }}",
1400 o.name
1401 )?;
1402 for (name, p) in &o.properties {
1403 let lc = snake_case(name);
1404 if p.is_object() {
1405 writeln!(
1406 r,
1407 " fn {}(&self) -> &{} {{
1408 &self.{0}
1409 }}
1410 fn {0}_mut(&mut self) -> &mut {1} {{
1411 &mut self.{0}
1412 }}",
1413 lc,
1414 rust_return_type(p)
1415 )?;
1416 } else if p.rust_by_function {
1417 writeln!(
1418 r,
1419 " fn {}<F>(&self, getter: F)
1420 where
1421 F: FnOnce({}),
1422 {{
1423 getter(&self.{0})
1424 }}",
1425 lc,
1426 rust_return_type(p)
1427 )?;
1428 } else {
1429 writeln!(r, " fn {}(&self) -> {} {{", lc, rust_return_type(p))?;
1430 if p.is_complex() {
1431 if p.optional {
1432 writeln!(r, " self.{}.as_ref().map(|p| &p[..])", lc)?;
1433 } else {
1434 writeln!(r, " &self.{}", lc)?;
1435 }
1436 } else {
1437 writeln!(r, " self.{}", lc)?;
1438 }
1439 writeln!(r, " }}")?;
1440 }
1441 if !p.is_object() && p.write {
1442 let bytearray = p.property_type == Type::Simple(SimpleType::QByteArray);
1443 let (t, v) = if bytearray && p.optional {
1444 ("Option<&[u8]>".to_string(), ".map(|v| v.to_vec())")
1445 } else if bytearray {
1446 ("&[u8]".to_string(), ".to_vec()")
1447 } else {
1448 (rust_type(p), "")
1449 };
1450 writeln!(
1451 r,
1452 " fn set_{}(&mut self, value: {}) {{
1453 self.{0} = value{};
1454 self.emit.{0}_changed();
1455 }}",
1456 lc, t, v
1457 )?;
1458 }
1459 }
1460 if o.object_type == ObjectType::List {
1461 writeln!(
1462 r,
1463 " fn row_count(&self) -> usize {{\n self.list.len()\n }}"
1464 )?;
1465 } else if o.object_type == ObjectType::Tree {
1466 writeln!(
1467 r,
1468 " fn row_count(&self, item: Option<usize>) -> usize {{
1469 self.list.len()
1470 }}
1471 fn index(&self, item: Option<usize>, row: usize) -> usize {{
1472 0
1473 }}
1474 fn parent(&self, index: usize) -> Option<usize> {{
1475 None
1476 }}
1477 fn row(&self, index: usize) -> usize {{
1478 index
1479 }}
1480 fn check_row(&self, index: usize, _row: usize) -> Option<usize> {{
1481 if index < self.list.len() {{
1482 Some(index)
1483 }} else {{
1484 None
1485 }}
1486 }}"
1487 )?;
1488 }
1489 if o.object_type != ObjectType::Object {
1490 for (name, ip) in &o.item_properties {
1491 let lc = snake_case(name);
1492 writeln!(
1493 r,
1494 " fn {}(&self, index: usize) -> {} {{",
1495 lc,
1496 rust_return_type_(ip)
1497 )?;
1498 if ip.is_complex() && ip.optional {
1499 writeln!(
1500 r,
1501 " self.list[index].{}.as_ref().map(|v| &v[..])",
1502 lc
1503 )?;
1504 } else if ip.is_complex() {
1505 writeln!(r, " &self.list[index].{}", lc)?;
1506 } else {
1507 writeln!(r, " self.list[index].{}", lc)?;
1508 }
1509 writeln!(r, " }}")?;
1510 let bytearray = ip.item_property_type == SimpleType::QByteArray;
1511 if ip.write && bytearray && ip.optional {
1512 writeln!(
1513 r,
1514 " fn set_{}(&mut self, index: usize, v: Option<&[u8]>) -> bool {{
1515 self.list[index].{0} = v.map(|v| v.to_vec());
1516 true
1517 }}",
1518 lc
1519 )?;
1520 } else if ip.write && bytearray {
1521 writeln!(
1522 r,
1523 " fn set_{}(&mut self, index: usize, v: &[u8]) -> bool {{
1524 self.list[index].{0} = v.to_vec();
1525 true
1526 }}",
1527 lc
1528 )?;
1529 } else if ip.write {
1530 writeln!(
1531 r,
1532 " fn set_{}(&mut self, index: usize, v: {}) -> bool {{
1533 self.list[index].{0} = v;
1534 true
1535 }}",
1536 lc,
1537 rust_type_(ip)
1538 )?;
1539 }
1540 }
1541 }
1542 writeln!(r, "}}")
1543 }
1544
1545 pub fn write_implementation(conf: &Config) -> Result<()> {
1546 let mut file = conf
1547 .config_file
1548 .parent()
1549 .unwrap()
1550 .join(&conf.rust.dir)
1551 .join("src")
1552 .join(&conf.rust.implementation_module);
1553 if !conf.overwrite_implementation && file.exists() {
1554 return Ok(());
1555 }
1556 file.set_extension("rs");
1557 if !conf.overwrite_implementation && file.exists() {
1558 return Ok(());
1559 }
1560 let mut r = Vec::new();
1561 writeln!(
1562 r,
1563 "#![allow(unused_imports)]
1564 #![allow(unused_variables)]
1565 #![allow(dead_code)]
1566 #![allow(unused_unit)]
1567 use {}{}::*;
1568 ",
1569 get_module_prefix(conf),
1570 conf.rust.interface_module
1571 )?;
1572
1573 for object in conf.objects.values() {
1574 write_rust_implementation_object(&mut r, object)?;
1575 }
1576 write_if_different(file, &r)
1577 }
1578
1579 /// Inspects the rust edition of the target crate to decide how the module
1580 /// imports should be written.
1581 ///
1582 /// As of Rust 2018, modules inside the crate should be prefixed with `crate::`.
1583 /// Prior to the 2018 edition, crate-local modules could be imported without
1584 /// this prefix.
1585 fn get_module_prefix(conf: &Config) -> &'static str {
1586 match conf.rust_edition {
1587 RustEdition::Rust2015 => "",
1588 _ => "crate::"
1589 }
1590 }