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 if o.object_type == ObjectType::List { 0322 writeln!(r, " new_data_ready: extern fn(*mut {}QObject),", o.name)?; 0323 } else if o.object_type == ObjectType::Tree { 0324 writeln!( 0325 r, 0326 " new_data_ready: extern fn(*mut {}QObject, index: COption<usize>),", 0327 o.name 0328 )?; 0329 } 0330 writeln!( 0331 r, 0332 "}} 0333 0334 unsafe impl Send for {}Emitter {{}} 0335 0336 impl {0}Emitter {{ 0337 /// Clone the emitter 0338 /// 0339 /// The emitter can only be cloned when it is mutable. The emitter calls 0340 /// into C++ code which may call into Rust again. If emmitting is possible 0341 /// from immutable structures, that might lead to access to a mutable 0342 /// reference. That is undefined behaviour and forbidden. 0343 pub fn clone(&mut self) -> {0}Emitter {{ 0344 {0}Emitter {{ 0345 qobject: self.qobject.clone(),", 0346 o.name 0347 )?; 0348 for (name, p) in &o.properties { 0349 if p.is_object() { 0350 continue; 0351 } 0352 writeln!( 0353 r, 0354 " {}_changed: self.{0}_changed,", 0355 snake_case(name), 0356 )?; 0357 } 0358 if o.object_type != ObjectType::Object { 0359 writeln!(r, " new_data_ready: self.new_data_ready,")?; 0360 } 0361 writeln!( 0362 r, 0363 " }} 0364 }} 0365 fn clear(&self) {{ 0366 let n: *const {0}QObject = null(); 0367 self.qobject.store(n as *mut {0}QObject, Ordering::SeqCst); 0368 }}", 0369 o.name 0370 )?; 0371 0372 for (name, p) in &o.properties { 0373 if p.is_object() { 0374 continue; 0375 } 0376 writeln!( 0377 r, 0378 " pub fn {}_changed(&mut self) {{ 0379 let ptr = self.qobject.load(Ordering::SeqCst); 0380 if !ptr.is_null() {{ 0381 (self.{0}_changed)(ptr); 0382 }} 0383 }}", 0384 snake_case(name) 0385 )?; 0386 } 0387 0388 if o.object_type == ObjectType::List { 0389 writeln!( 0390 r, 0391 " pub fn new_data_ready(&mut self) {{ 0392 let ptr = self.qobject.load(Ordering::SeqCst); 0393 if !ptr.is_null() {{ 0394 (self.new_data_ready)(ptr); 0395 }} 0396 }}" 0397 )?; 0398 } else if o.object_type == ObjectType::Tree { 0399 writeln!( 0400 r, 0401 " pub fn new_data_ready(&mut self, item: Option<usize>) {{ 0402 let ptr = self.qobject.load(Ordering::SeqCst); 0403 if !ptr.is_null() {{ 0404 (self.new_data_ready)(ptr, item.into()); 0405 }} 0406 }}" 0407 )?; 0408 } 0409 0410 let mut model_struct = String::new(); 0411 if o.object_type != ObjectType::Object { 0412 let type_ = if o.object_type == ObjectType::List { 0413 "List" 0414 } else { 0415 "Tree" 0416 }; 0417 model_struct = format!(", model: {}{}", o.name, type_); 0418 let mut index = ""; 0419 let mut index_decl = ""; 0420 let mut index_c_decl = ""; 0421 let mut dest = ""; 0422 let mut dest_decl = ""; 0423 let mut dest_c_decl = ""; 0424 if o.object_type == ObjectType::Tree { 0425 index_decl = " index: Option<usize>,"; 0426 index_c_decl = " index: COption<usize>,"; 0427 index = " index.into(),"; 0428 dest_decl = " dest: Option<usize>,"; 0429 dest_c_decl = " dest: COption<usize>,"; 0430 dest = " dest.into(),"; 0431 } 0432 writeln!( 0433 r, 0434 "}} 0435 0436 #[derive(Clone)] 0437 pub struct {0}{1} {{ 0438 qobject: *mut {0}QObject, 0439 layout_about_to_be_changed: extern fn(*mut {0}QObject), 0440 layout_changed: extern fn(*mut {0}QObject), 0441 data_changed: extern fn(*mut {0}QObject, usize, usize), 0442 begin_reset_model: extern fn(*mut {0}QObject), 0443 end_reset_model: extern fn(*mut {0}QObject), 0444 begin_insert_rows: extern fn(*mut {0}QObject,{4} usize, usize), 0445 end_insert_rows: extern fn(*mut {0}QObject), 0446 begin_move_rows: extern fn(*mut {0}QObject,{4} usize, usize,{7} usize), 0447 end_move_rows: extern fn(*mut {0}QObject), 0448 begin_remove_rows: extern fn(*mut {0}QObject,{4} usize, usize), 0449 end_remove_rows: extern fn(*mut {0}QObject), 0450 }} 0451 0452 impl {0}{1} {{ 0453 pub fn layout_about_to_be_changed(&mut self) {{ 0454 (self.layout_about_to_be_changed)(self.qobject); 0455 }} 0456 pub fn layout_changed(&mut self) {{ 0457 (self.layout_changed)(self.qobject); 0458 }} 0459 pub fn data_changed(&mut self, first: usize, last: usize) {{ 0460 (self.data_changed)(self.qobject, first, last); 0461 }} 0462 pub fn begin_reset_model(&mut self) {{ 0463 (self.begin_reset_model)(self.qobject); 0464 }} 0465 pub fn end_reset_model(&mut self) {{ 0466 (self.end_reset_model)(self.qobject); 0467 }} 0468 pub fn begin_insert_rows(&mut self,{2} first: usize, last: usize) {{ 0469 (self.begin_insert_rows)(self.qobject,{3} first, last); 0470 }} 0471 pub fn end_insert_rows(&mut self) {{ 0472 (self.end_insert_rows)(self.qobject); 0473 }} 0474 pub fn begin_move_rows(&mut self,{2} first: usize, last: usize,{5} destination: usize) {{ 0475 (self.begin_move_rows)(self.qobject,{3} first, last,{6} destination); 0476 }} 0477 pub fn end_move_rows(&mut self) {{ 0478 (self.end_move_rows)(self.qobject); 0479 }} 0480 pub fn begin_remove_rows(&mut self,{2} first: usize, last: usize) {{ 0481 (self.begin_remove_rows)(self.qobject,{3} first, last); 0482 }} 0483 pub fn end_remove_rows(&mut self) {{ 0484 (self.end_remove_rows)(self.qobject); 0485 }}", 0486 o.name, type_, index_decl, index, index_c_decl, dest_decl, dest, dest_c_decl 0487 )?; 0488 } 0489 0490 write!( 0491 r, 0492 "}} 0493 0494 pub trait {}Trait {{ 0495 fn new(emit: {0}Emitter{}", 0496 o.name, model_struct 0497 )?; 0498 for (name, p) in &o.properties { 0499 if p.is_object() { 0500 write!(r, ",\n {}: {}", snake_case(name), p.type_name())?; 0501 } 0502 } 0503 writeln!( 0504 r, 0505 ") -> Self; 0506 fn emit(&mut self) -> &mut {}Emitter;", 0507 o.name 0508 )?; 0509 for (name, p) in &o.properties { 0510 let lc = snake_case(name).to_lowercase(); 0511 if p.is_object() { 0512 writeln!(r, " fn {}(&self) -> &{};", lc, rust_type(p))?; 0513 writeln!(r, " fn {}_mut(&mut self) -> &mut {};", lc, rust_type(p))?; 0514 } else { 0515 if p.rust_by_function { 0516 write!( 0517 r, 0518 " fn {}<F>(&self, getter: F) where F: FnOnce({});", 0519 lc, 0520 rust_return_type(p) 0521 )?; 0522 } else { 0523 writeln!(r, " fn {}(&self) -> {};", lc, rust_return_type(p))?; 0524 } 0525 if p.write { 0526 if p.type_name() == "QByteArray" { 0527 if p.optional { 0528 writeln!(r, " fn set_{}(&mut self, value: Option<&[u8]>);", lc)?; 0529 } else { 0530 writeln!(r, " fn set_{}(&mut self, value: &[u8]);", lc)?; 0531 } 0532 } else { 0533 writeln!(r, " fn set_{}(&mut self, value: {});", lc, rust_type(p))?; 0534 } 0535 } 0536 } 0537 } 0538 for (name, f) in &o.functions { 0539 let lc = snake_case(name); 0540 let mut arg_list = String::new(); 0541 if !f.arguments.is_empty() { 0542 for a in &f.arguments { 0543 let t = if a.argument_type.name() == "QByteArray" { 0544 "&[u8]" 0545 } else { 0546 a.argument_type.rust_type() 0547 }; 0548 arg_list.push_str(&format!(", {}: {}", a.name, t)); 0549 } 0550 } 0551 writeln!( 0552 r, 0553 " fn {}(&{}self{}) -> {};", 0554 lc, 0555 if f.mutable { "mut " } else { "" }, 0556 arg_list, 0557 f.return_type.rust_type() 0558 )?; 0559 } 0560 if o.object_type == ObjectType::List { 0561 writeln!( 0562 r, 0563 " fn row_count(&self) -> usize; 0564 fn insert_rows(&mut self, _row: usize, _count: usize) -> bool {{ false }} 0565 fn remove_rows(&mut self, _row: usize, _count: usize) -> bool {{ false }} 0566 fn can_fetch_more(&self) -> bool {{ 0567 false 0568 }} 0569 fn fetch_more(&mut self) {{}} 0570 fn sort(&mut self, _: u8, _: SortOrder) {{}}" 0571 )?; 0572 } else if o.object_type == ObjectType::Tree { 0573 writeln!( 0574 r, 0575 " fn row_count(&self, _: Option<usize>) -> usize; 0576 fn can_fetch_more(&self, _: Option<usize>) -> bool {{ 0577 false 0578 }} 0579 fn fetch_more(&mut self, _: Option<usize>) {{}} 0580 fn sort(&mut self, _: u8, _: SortOrder) {{}} 0581 fn check_row(&self, index: usize, row: usize) -> Option<usize>; 0582 fn index(&self, item: Option<usize>, row: usize) -> usize; 0583 fn parent(&self, index: usize) -> Option<usize>; 0584 fn row(&self, index: usize) -> usize;" 0585 )?; 0586 } 0587 if o.object_type != ObjectType::Object { 0588 for (name, ip) in &o.item_properties { 0589 let name = snake_case(name); 0590 writeln!( 0591 r, 0592 " fn {}(&self, index: usize) -> {};", 0593 name, 0594 rust_return_type_(ip) 0595 )?; 0596 if ip.write { 0597 if ip.item_property_type.name() == "QByteArray" { 0598 if ip.optional { 0599 writeln!( 0600 r, 0601 " fn set_{}(&mut self, index: usize, _: Option<&[u8]>) -> bool;", 0602 name 0603 )?; 0604 } else { 0605 writeln!( 0606 r, 0607 " fn set_{}(&mut self, index: usize, _: &[u8]) -> bool;", 0608 name 0609 )?; 0610 } 0611 } else { 0612 writeln!( 0613 r, 0614 " fn set_{}(&mut self, index: usize, _: {}) -> bool;", 0615 name, 0616 rust_type_(ip) 0617 )?; 0618 } 0619 } 0620 } 0621 } 0622 writeln!( 0623 r, 0624 "}} 0625 0626 #[no_mangle] 0627 pub extern \"C\" fn {}_new(", 0628 lcname 0629 )?; 0630 r_constructor_args_decl(r, &lcname, o, conf)?; 0631 writeln!(r, ",\n) -> *mut {} {{", o.name)?; 0632 r_constructor_args(r, &lcname, o, conf)?; 0633 writeln!( 0634 r, 0635 " Box::into_raw(Box::new(d_{})) 0636 }} 0637 0638 #[no_mangle] 0639 pub unsafe extern \"C\" fn {0}_free(ptr: *mut {}) {{ 0640 Box::from_raw(ptr).emit().clear(); 0641 }}", 0642 lcname, o.name 0643 )?; 0644 0645 for (name, p) in &o.properties { 0646 let base = format!("{}_{}", lcname, snake_case(name)); 0647 if p.is_object() { 0648 writeln!( 0649 r, 0650 " 0651 #[no_mangle] 0652 pub unsafe extern \"C\" fn {}_get(ptr: *mut {}) -> *mut {} {{ 0653 (&mut *ptr).{}_mut() 0654 }}", 0655 base, 0656 o.name, 0657 rust_type(p), 0658 snake_case(name) 0659 )?; 0660 } else if p.is_complex() && !p.optional { 0661 if p.rust_by_function { 0662 writeln!( 0663 r, 0664 " 0665 #[no_mangle] 0666 pub unsafe extern \"C\" fn {}_get( 0667 ptr: *const {}, 0668 p: *mut {}, 0669 set: extern fn(*mut {2}, *const c_char, c_int), 0670 ) {{ 0671 let o = &*ptr; 0672 o.{}(|v| {{ 0673 let s: *const c_char = v.as_ptr() as *const c_char; 0674 set(p, s, to_c_int(v.len())); 0675 }}); 0676 }}", 0677 base, 0678 o.name, 0679 p.type_name(), 0680 snake_case(name) 0681 )?; 0682 } else { 0683 writeln!( 0684 r, 0685 " 0686 #[no_mangle] 0687 pub unsafe extern \"C\" fn {}_get( 0688 ptr: *const {}, 0689 p: *mut {}, 0690 set: extern fn(*mut {2}, *const c_char, c_int), 0691 ) {{ 0692 let o = &*ptr; 0693 let v = o.{}(); 0694 let s: *const c_char = v.as_ptr() as *const c_char; 0695 set(p, s, to_c_int(v.len())); 0696 }}", 0697 base, 0698 o.name, 0699 p.type_name(), 0700 snake_case(name) 0701 )?; 0702 } 0703 if p.write && p.type_name() == "QString" { 0704 writeln!( 0705 r, 0706 " 0707 #[no_mangle] 0708 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_ushort, len: c_int) {{ 0709 let o = &mut *ptr; 0710 let mut s = String::new(); 0711 set_string_from_utf16(&mut s, v, len); 0712 o.set_{}(s); 0713 }}", 0714 base, 0715 o.name, 0716 snake_case(name) 0717 )?; 0718 } else if p.write { 0719 writeln!( 0720 r, 0721 " 0722 #[no_mangle] 0723 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_char, len: c_int) {{ 0724 let o = &mut *ptr; 0725 let v = slice::from_raw_parts(v as *const u8, to_usize(len)); 0726 o.set_{}(v); 0727 }}", 0728 base, 0729 o.name, 0730 snake_case(name) 0731 )?; 0732 } 0733 } else if p.is_complex() { 0734 writeln!( 0735 r, 0736 " 0737 #[no_mangle] 0738 pub unsafe extern \"C\" fn {}_get( 0739 ptr: *const {}, 0740 p: *mut {}, 0741 set: extern fn(*mut {2}, *const c_char, c_int), 0742 ) {{ 0743 let o = &*ptr; 0744 let v = o.{}(); 0745 if let Some(v) = v {{ 0746 let s: *const c_char = v.as_ptr() as *const c_char; 0747 set(p, s, to_c_int(v.len())); 0748 }} 0749 }}", 0750 base, 0751 o.name, 0752 p.type_name(), 0753 snake_case(name) 0754 )?; 0755 if p.write && p.type_name() == "QString" { 0756 writeln!( 0757 r, 0758 " 0759 #[no_mangle] 0760 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_ushort, len: c_int) {{ 0761 let o = &mut *ptr; 0762 let mut s = String::new(); 0763 set_string_from_utf16(&mut s, v, len); 0764 o.set_{}(Some(s)); 0765 }}", 0766 base, 0767 o.name, 0768 snake_case(name) 0769 )?; 0770 } else if p.write { 0771 writeln!( 0772 r, 0773 " 0774 #[no_mangle] 0775 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: *const c_char, len: c_int) {{ 0776 let o = &mut *ptr; 0777 let v = slice::from_raw_parts(v as *const u8, to_usize(len)); 0778 o.set_{}(Some(v.into())); 0779 }}", 0780 base, 0781 o.name, 0782 snake_case(name) 0783 )?; 0784 } 0785 } else if p.optional { 0786 writeln!( 0787 r, 0788 " 0789 #[no_mangle] 0790 pub unsafe extern \"C\" fn {}_get(ptr: *const {}) -> COption<{}> {{ 0791 match (&*ptr).{}() {{ 0792 Some(value) => COption {{ data: value, some: true }}, 0793 None => COption {{ data: {2}::default(), some: false}} 0794 }} 0795 }}", 0796 base, 0797 o.name, 0798 p.property_type.rust_type(), 0799 snake_case(name) 0800 )?; 0801 if p.write { 0802 writeln!( 0803 r, 0804 " 0805 #[no_mangle] 0806 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: {}) {{ 0807 (&mut *ptr).set_{}(Some(v)); 0808 }}", 0809 base, 0810 o.name, 0811 p.property_type.rust_type(), 0812 snake_case(name) 0813 )?; 0814 } 0815 } else { 0816 writeln!( 0817 r, 0818 " 0819 #[no_mangle] 0820 pub unsafe extern \"C\" fn {}_get(ptr: *const {}) -> {} {{ 0821 (&*ptr).{}() 0822 }}", 0823 base, 0824 o.name, 0825 rust_type(p), 0826 snake_case(name) 0827 )?; 0828 if p.write { 0829 writeln!( 0830 r, 0831 " 0832 #[no_mangle] 0833 pub unsafe extern \"C\" fn {}_set(ptr: *mut {}, v: {}) {{ 0834 (&mut *ptr).set_{}(v); 0835 }}", 0836 base, 0837 o.name, 0838 rust_type(p), 0839 snake_case(name) 0840 )?; 0841 } 0842 } 0843 if p.write && p.optional { 0844 writeln!( 0845 r, 0846 " 0847 #[no_mangle] 0848 pub unsafe extern \"C\" fn {}_set_none(ptr: *mut {}) {{ 0849 let o = &mut *ptr; 0850 o.set_{}(None); 0851 }}", 0852 base, 0853 o.name, 0854 snake_case(name) 0855 )?; 0856 } 0857 } 0858 for f in &o.functions { 0859 write_function(r, f, &lcname, o)?; 0860 } 0861 if o.object_type == ObjectType::List { 0862 writeln!( 0863 r, 0864 " 0865 #[no_mangle] 0866 pub unsafe extern \"C\" fn {1}_row_count(ptr: *const {0}) -> c_int {{ 0867 to_c_int((&*ptr).row_count()) 0868 }} 0869 #[no_mangle] 0870 pub unsafe extern \"C\" fn {1}_insert_rows(ptr: *mut {0}, row: c_int, count: c_int) -> bool {{ 0871 (&mut *ptr).insert_rows(to_usize(row), to_usize(count)) 0872 }} 0873 #[no_mangle] 0874 pub unsafe extern \"C\" fn {1}_remove_rows(ptr: *mut {0}, row: c_int, count: c_int) -> bool {{ 0875 (&mut *ptr).remove_rows(to_usize(row), to_usize(count)) 0876 }} 0877 #[no_mangle] 0878 pub unsafe extern \"C\" fn {1}_can_fetch_more(ptr: *const {0}) -> bool {{ 0879 (&*ptr).can_fetch_more() 0880 }} 0881 #[no_mangle] 0882 pub unsafe extern \"C\" fn {1}_fetch_more(ptr: *mut {0}) {{ 0883 (&mut *ptr).fetch_more() 0884 }} 0885 #[no_mangle] 0886 pub unsafe extern \"C\" fn {1}_sort( 0887 ptr: *mut {0}, 0888 column: u8, 0889 order: SortOrder, 0890 ) {{ 0891 (&mut *ptr).sort(column, order) 0892 }}", 0893 o.name, lcname 0894 )?; 0895 } else if o.object_type == ObjectType::Tree { 0896 writeln!( 0897 r, 0898 " 0899 #[no_mangle] 0900 pub unsafe extern \"C\" fn {1}_row_count( 0901 ptr: *const {0}, 0902 index: COption<usize>, 0903 ) -> c_int {{ 0904 to_c_int((&*ptr).row_count(index.into())) 0905 }} 0906 #[no_mangle] 0907 pub unsafe extern \"C\" fn {1}_can_fetch_more( 0908 ptr: *const {0}, 0909 index: COption<usize>, 0910 ) -> bool {{ 0911 (&*ptr).can_fetch_more(index.into()) 0912 }} 0913 #[no_mangle] 0914 pub unsafe extern \"C\" fn {1}_fetch_more(ptr: *mut {0}, index: COption<usize>) {{ 0915 (&mut *ptr).fetch_more(index.into()) 0916 }} 0917 #[no_mangle] 0918 pub unsafe extern \"C\" fn {1}_sort( 0919 ptr: *mut {0}, 0920 column: u8, 0921 order: SortOrder 0922 ) {{ 0923 (&mut *ptr).sort(column, order) 0924 }} 0925 #[no_mangle] 0926 pub unsafe extern \"C\" fn {1}_check_row( 0927 ptr: *const {0}, 0928 index: usize, 0929 row: c_int, 0930 ) -> COption<usize> {{ 0931 (&*ptr).check_row(index, to_usize(row)).into() 0932 }} 0933 #[no_mangle] 0934 pub unsafe extern \"C\" fn {1}_index( 0935 ptr: *const {0}, 0936 index: COption<usize>, 0937 row: c_int, 0938 ) -> usize {{ 0939 (&*ptr).index(index.into(), to_usize(row)) 0940 }} 0941 #[no_mangle] 0942 pub unsafe extern \"C\" fn {1}_parent(ptr: *const {0}, index: usize) -> QModelIndex {{ 0943 if let Some(parent) = (&*ptr).parent(index) {{ 0944 QModelIndex {{ 0945 row: to_c_int((&*ptr).row(parent)), 0946 internal_id: parent, 0947 }} 0948 }} else {{ 0949 QModelIndex {{ 0950 row: -1, 0951 internal_id: 0, 0952 }} 0953 }} 0954 }} 0955 #[no_mangle] 0956 pub unsafe extern \"C\" fn {1}_row(ptr: *const {0}, index: usize) -> c_int {{ 0957 to_c_int((&*ptr).row(index)) 0958 }}", 0959 o.name, lcname 0960 )?; 0961 } 0962 if o.object_type != ObjectType::Object { 0963 let (index_decl, index) = if o.object_type == ObjectType::Tree { 0964 (", index: usize", "index") 0965 } else { 0966 (", row: c_int", "to_usize(row)") 0967 }; 0968 for (name, ip) in &o.item_properties { 0969 if ip.is_complex() && !ip.optional { 0970 writeln!( 0971 r, 0972 " 0973 #[no_mangle] 0974 pub unsafe extern \"C\" fn {}_data_{}( 0975 ptr: *const {}{}, 0976 d: *mut {}, 0977 set: extern fn(*mut {4}, *const c_char, len: c_int), 0978 ) {{ 0979 let o = &*ptr; 0980 let data = o.{1}({}); 0981 let s: *const c_char = data.as_ptr() as *const c_char; 0982 set(d, s, to_c_int(data.len())); 0983 }}", 0984 lcname, 0985 snake_case(name), 0986 o.name, 0987 index_decl, 0988 ip.type_name(), 0989 index 0990 )?; 0991 } else if ip.is_complex() { 0992 writeln!( 0993 r, 0994 " 0995 #[no_mangle] 0996 pub unsafe extern \"C\" fn {}_data_{}( 0997 ptr: *const {}{}, 0998 d: *mut {}, 0999 set: extern fn(*mut {4}, *const c_char, len: c_int), 1000 ) {{ 1001 let o = &*ptr; 1002 let data = o.{1}({}); 1003 if let Some(data) = data {{ 1004 let s: *const c_char = data.as_ptr() as *const c_char; 1005 set(d, s, to_c_int(data.len())); 1006 }} 1007 }}", 1008 lcname, 1009 snake_case(name), 1010 o.name, 1011 index_decl, 1012 ip.type_name(), 1013 index 1014 )?; 1015 } else { 1016 writeln!( 1017 r, 1018 " 1019 #[no_mangle] 1020 pub unsafe extern \"C\" fn {}_data_{}(ptr: *const {}{}) -> {} {{ 1021 let o = &*ptr; 1022 o.{1}({}){} 1023 }}", 1024 lcname, 1025 snake_case(name), 1026 o.name, 1027 index_decl, 1028 rust_c_type(ip), 1029 index, 1030 if ip.optional { ".into()" } else { "" } 1031 )?; 1032 } 1033 if ip.write { 1034 let val = if ip.optional { "Some(v)" } else { "v" }; 1035 if ip.type_name() == "QString" { 1036 writeln!( 1037 r, 1038 " 1039 #[no_mangle] 1040 pub unsafe extern \"C\" fn {}_set_data_{}( 1041 ptr: *mut {}{}, 1042 s: *const c_ushort, len: c_int, 1043 ) -> bool {{ 1044 let o = &mut *ptr; 1045 let mut v = String::new(); 1046 set_string_from_utf16(&mut v, s, len); 1047 o.set_{1}({}, {}) 1048 }}", 1049 lcname, 1050 snake_case(name), 1051 o.name, 1052 index_decl, 1053 index, 1054 val 1055 )?; 1056 } else if ip.type_name() == "QByteArray" { 1057 writeln!( 1058 r, 1059 " 1060 #[no_mangle] 1061 pub unsafe extern \"C\" fn {}_set_data_{}( 1062 ptr: *mut {}{}, 1063 s: *const c_char, len: c_int, 1064 ) -> bool {{ 1065 let o = &mut *ptr; 1066 let slice = ::std::slice::from_raw_parts(s as *const u8, to_usize(len)); 1067 o.set_{1}({}, {}) 1068 }}", 1069 lcname, 1070 snake_case(name), 1071 o.name, 1072 index_decl, 1073 index, 1074 if ip.optional { "Some(slice)" } else { "slice" } 1075 )?; 1076 } else { 1077 let type_ = ip.item_property_type.rust_type(); 1078 writeln!( 1079 r, 1080 " 1081 #[no_mangle] 1082 pub unsafe extern \"C\" fn {}_set_data_{}( 1083 ptr: *mut {}{}, 1084 v: {}, 1085 ) -> bool {{ 1086 (&mut *ptr).set_{1}({}, {}) 1087 }}", 1088 lcname, 1089 snake_case(name), 1090 o.name, 1091 index_decl, 1092 type_, 1093 index, 1094 val 1095 )?; 1096 } 1097 } 1098 if ip.write && ip.optional { 1099 writeln!( 1100 r, 1101 " 1102 #[no_mangle] 1103 pub unsafe extern \"C\" fn {}_set_data_{}_none(ptr: *mut {}{}) -> bool {{ 1104 (&mut *ptr).set_{1}({}, None) 1105 }}", 1106 lcname, 1107 snake_case(name), 1108 o.name, 1109 index_decl, 1110 index 1111 )?; 1112 } 1113 } 1114 } 1115 Ok(()) 1116 } 1117 1118 fn write_rust_types(conf: &Config, r: &mut Vec<u8>) -> Result<()> { 1119 let mut has_option = false; 1120 let mut has_string = false; 1121 let mut has_byte_array = false; 1122 let mut has_list_or_tree = false; 1123 1124 for o in conf.objects.values() { 1125 has_list_or_tree |= o.object_type != ObjectType::Object; 1126 for p in o.properties.values() { 1127 has_option |= p.optional; 1128 has_string |= p.property_type == Type::Simple(SimpleType::QString); 1129 has_byte_array |= p.property_type == Type::Simple(SimpleType::QByteArray); 1130 } 1131 for p in o.item_properties.values() { 1132 has_option |= p.optional; 1133 has_string |= p.item_property_type == SimpleType::QString; 1134 has_byte_array |= p.item_property_type == SimpleType::QByteArray; 1135 } 1136 for f in o.functions.values() { 1137 has_string |= f.return_type == SimpleType::QString; 1138 has_byte_array |= f.return_type == SimpleType::QByteArray; 1139 for a in &f.arguments { 1140 has_string |= a.argument_type == SimpleType::QString; 1141 has_byte_array |= a.argument_type == SimpleType::QByteArray; 1142 } 1143 } 1144 } 1145 1146 if has_option || has_list_or_tree { 1147 writeln!( 1148 r, 1149 " 1150 1151 #[repr(C)] 1152 pub struct COption<T> {{ 1153 data: T, 1154 some: bool, 1155 }} 1156 1157 impl<T> COption<T> {{ 1158 #![allow(dead_code)] 1159 fn into(self) -> Option<T> {{ 1160 if self.some {{ 1161 Some(self.data) 1162 }} else {{ 1163 None 1164 }} 1165 }} 1166 }} 1167 1168 impl<T> From<Option<T>> for COption<T> 1169 where 1170 T: Default, 1171 {{ 1172 fn from(t: Option<T>) -> COption<T> {{ 1173 if let Some(v) = t {{ 1174 COption {{ 1175 data: v, 1176 some: true, 1177 }} 1178 }} else {{ 1179 COption {{ 1180 data: T::default(), 1181 some: false, 1182 }} 1183 }} 1184 }} 1185 }}" 1186 )?; 1187 } 1188 if has_string { 1189 writeln!( 1190 r, 1191 " 1192 1193 pub enum QString {{}} 1194 1195 fn set_string_from_utf16(s: &mut String, str: *const c_ushort, len: c_int) {{ 1196 let utf16 = unsafe {{ slice::from_raw_parts(str, to_usize(len)) }}; 1197 let characters = decode_utf16(utf16.iter().cloned()) 1198 .map(|r| r.unwrap()); 1199 s.clear(); 1200 s.extend(characters); 1201 }} 1202 " 1203 )?; 1204 } 1205 if has_byte_array { 1206 writeln!( 1207 r, 1208 " 1209 1210 pub enum QByteArray {{}}" 1211 )?; 1212 } 1213 if has_list_or_tree { 1214 writeln!( 1215 r, 1216 " 1217 1218 #[repr(C)] 1219 #[derive(PartialEq, Eq, Debug)] 1220 pub enum SortOrder {{ 1221 Ascending = 0, 1222 Descending = 1, 1223 }} 1224 1225 #[repr(C)] 1226 pub struct QModelIndex {{ 1227 row: c_int, 1228 internal_id: usize, 1229 }}" 1230 )?; 1231 } 1232 1233 if has_string || has_byte_array || has_list_or_tree { 1234 writeln!( 1235 r, 1236 " 1237 1238 fn to_usize(n: c_int) -> usize {{ 1239 if n < 0 {{ 1240 panic!(\"Cannot cast {{}} to usize\", n); 1241 }} 1242 n as usize 1243 }} 1244 " 1245 )?; 1246 } 1247 1248 if has_string || has_byte_array || has_list_or_tree { 1249 writeln!( 1250 r, 1251 " 1252 fn to_c_int(n: usize) -> c_int {{ 1253 if n > c_int::max_value() as usize {{ 1254 panic!(\"Cannot cast {{}} to c_int\", n); 1255 }} 1256 n as c_int 1257 }} 1258 " 1259 )?; 1260 } 1261 Ok(()) 1262 } 1263 1264 pub fn write_interface(conf: &Config) -> Result<()> { 1265 let mut r = Vec::new(); 1266 writeln!( 1267 r, 1268 "/* generated by rust_qt_binding_generator */ 1269 use libc::{{c_char, c_ushort, c_int}}; 1270 use std::slice; 1271 use std::char::decode_utf16; 1272 1273 use std::sync::Arc; 1274 use std::sync::atomic::{{AtomicPtr, Ordering}}; 1275 use std::ptr::null; 1276 1277 use {}{}::*;", 1278 get_module_prefix(conf), 1279 conf.rust.implementation_module 1280 )?; 1281 1282 write_rust_types(conf, &mut r)?; 1283 1284 for object in conf.objects.values() { 1285 write_rust_interface_object(&mut r, object, conf)?; 1286 } 1287 let mut file = conf 1288 .config_file 1289 .parent() 1290 .unwrap() 1291 .join(&conf.rust.dir) 1292 .join("src") 1293 .join(&conf.rust.interface_module); 1294 file.set_extension("rs"); 1295 write_if_different(file, &r) 1296 } 1297 1298 fn write_rust_implementation_object(r: &mut Vec<u8>, o: &Object) -> Result<()> { 1299 if o.object_type != ObjectType::Object { 1300 writeln!(r, "#[derive(Default, Clone)]")?; 1301 writeln!(r, "struct {}Item {{", o.name)?; 1302 for (name, ip) in &o.item_properties { 1303 let lc = snake_case(name); 1304 if ip.optional { 1305 writeln!( 1306 r, 1307 " {}: Option<{}>,", 1308 lc, 1309 ip.item_property_type.rust_type() 1310 )?; 1311 } else { 1312 writeln!(r, " {}: {},", lc, ip.item_property_type.rust_type())?; 1313 } 1314 } 1315 writeln!(r, "}}\n")?; 1316 } 1317 let mut model_struct = String::new(); 1318 writeln!(r, "pub struct {} {{\n emit: {0}Emitter,", o.name)?; 1319 if o.object_type == ObjectType::List { 1320 model_struct = format!(", model: {}List", o.name); 1321 writeln!(r, " model: {}List,", o.name)?; 1322 } else if o.object_type == ObjectType::Tree { 1323 model_struct = format!(", model: {}Tree", o.name); 1324 writeln!(r, " model: {}Tree,", o.name)?; 1325 } 1326 for (name, p) in &o.properties { 1327 let lc = snake_case(name); 1328 writeln!(r, " {}: {},", lc, rust_type(p))?; 1329 } 1330 if o.object_type != ObjectType::Object { 1331 writeln!(r, " list: Vec<{}Item>,", o.name)?; 1332 } 1333 writeln!(r, "}}\n")?; 1334 for (name, p) in &o.properties { 1335 if p.is_object() { 1336 model_struct += &format!(", {}: {}", name, p.type_name()); 1337 } 1338 } 1339 writeln!( 1340 r, 1341 "impl {}Trait for {0} {{ 1342 fn new(emit: {0}Emitter{}) -> {0} {{ 1343 {0} {{ 1344 emit,", 1345 o.name, model_struct 1346 )?; 1347 if o.object_type != ObjectType::Object { 1348 writeln!(r, " model,")?; 1349 writeln!(r, " list: Vec::new(),")?; 1350 } 1351 for (name, p) in &o.properties { 1352 let lc = snake_case(name); 1353 if p.is_object() { 1354 writeln!(r, " {},", lc)?; 1355 } else { 1356 writeln!(r, " {}: {},", lc, rust_type_init(p))?; 1357 } 1358 } 1359 writeln!( 1360 r, 1361 " }} 1362 }} 1363 fn emit(&mut self) -> &mut {}Emitter {{ 1364 &self.emit 1365 }}", 1366 o.name 1367 )?; 1368 for (name, p) in &o.properties { 1369 let lc = snake_case(name); 1370 if p.is_object() { 1371 writeln!( 1372 r, 1373 " fn {}(&self) -> &{} {{ 1374 &self.{0} 1375 }} 1376 fn {0}_mut(&mut self) -> &mut {1} {{ 1377 &mut self.{0} 1378 }}", 1379 lc, 1380 rust_return_type(p) 1381 )?; 1382 } else if p.rust_by_function { 1383 writeln!( 1384 r, 1385 " fn {}<F>(&self, getter: F) 1386 where 1387 F: FnOnce({}), 1388 {{ 1389 getter(&self.{0}) 1390 }}", 1391 lc, 1392 rust_return_type(p) 1393 )?; 1394 } else { 1395 writeln!(r, " fn {}(&self) -> {} {{", lc, rust_return_type(p))?; 1396 if p.is_complex() { 1397 if p.optional { 1398 writeln!(r, " self.{}.as_ref().map(|p| &p[..])", lc)?; 1399 } else { 1400 writeln!(r, " &self.{}", lc)?; 1401 } 1402 } else { 1403 writeln!(r, " self.{}", lc)?; 1404 } 1405 writeln!(r, " }}")?; 1406 } 1407 if !p.is_object() && p.write { 1408 let bytearray = p.property_type == Type::Simple(SimpleType::QByteArray); 1409 let (t, v) = if bytearray && p.optional { 1410 ("Option<&[u8]>".to_string(), ".map(|v| v.to_vec())") 1411 } else if bytearray { 1412 ("&[u8]".to_string(), ".to_vec()") 1413 } else { 1414 (rust_type(p), "") 1415 }; 1416 writeln!( 1417 r, 1418 " fn set_{}(&mut self, value: {}) {{ 1419 self.{0} = value{}; 1420 self.emit.{0}_changed(); 1421 }}", 1422 lc, t, v 1423 )?; 1424 } 1425 } 1426 if o.object_type == ObjectType::List { 1427 writeln!( 1428 r, 1429 " fn row_count(&self) -> usize {{\n self.list.len()\n }}" 1430 )?; 1431 } else if o.object_type == ObjectType::Tree { 1432 writeln!( 1433 r, 1434 " fn row_count(&self, item: Option<usize>) -> usize {{ 1435 self.list.len() 1436 }} 1437 fn index(&self, item: Option<usize>, row: usize) -> usize {{ 1438 0 1439 }} 1440 fn parent(&self, index: usize) -> Option<usize> {{ 1441 None 1442 }} 1443 fn row(&self, index: usize) -> usize {{ 1444 index 1445 }} 1446 fn check_row(&self, index: usize, _row: usize) -> Option<usize> {{ 1447 if index < self.list.len() {{ 1448 Some(index) 1449 }} else {{ 1450 None 1451 }} 1452 }}" 1453 )?; 1454 } 1455 if o.object_type != ObjectType::Object { 1456 for (name, ip) in &o.item_properties { 1457 let lc = snake_case(name); 1458 writeln!( 1459 r, 1460 " fn {}(&self, index: usize) -> {} {{", 1461 lc, 1462 rust_return_type_(ip) 1463 )?; 1464 if ip.is_complex() && ip.optional { 1465 writeln!( 1466 r, 1467 " self.list[index].{}.as_ref().map(|v| &v[..])", 1468 lc 1469 )?; 1470 } else if ip.is_complex() { 1471 writeln!(r, " &self.list[index].{}", lc)?; 1472 } else { 1473 writeln!(r, " self.list[index].{}", lc)?; 1474 } 1475 writeln!(r, " }}")?; 1476 let bytearray = ip.item_property_type == SimpleType::QByteArray; 1477 if ip.write && bytearray && ip.optional { 1478 writeln!( 1479 r, 1480 " fn set_{}(&mut self, index: usize, v: Option<&[u8]>) -> bool {{ 1481 self.list[index].{0} = v.map(|v| v.to_vec()); 1482 true 1483 }}", 1484 lc 1485 )?; 1486 } else if ip.write && bytearray { 1487 writeln!( 1488 r, 1489 " fn set_{}(&mut self, index: usize, v: &[u8]) -> bool {{ 1490 self.list[index].{0} = v.to_vec(); 1491 true 1492 }}", 1493 lc 1494 )?; 1495 } else if ip.write { 1496 writeln!( 1497 r, 1498 " fn set_{}(&mut self, index: usize, v: {}) -> bool {{ 1499 self.list[index].{0} = v; 1500 true 1501 }}", 1502 lc, 1503 rust_type_(ip) 1504 )?; 1505 } 1506 } 1507 } 1508 writeln!(r, "}}") 1509 } 1510 1511 pub fn write_implementation(conf: &Config) -> Result<()> { 1512 let mut file = conf 1513 .config_file 1514 .parent() 1515 .unwrap() 1516 .join(&conf.rust.dir) 1517 .join("src") 1518 .join(&conf.rust.implementation_module); 1519 if !conf.overwrite_implementation && file.exists() { 1520 return Ok(()); 1521 } 1522 file.set_extension("rs"); 1523 if !conf.overwrite_implementation && file.exists() { 1524 return Ok(()); 1525 } 1526 let mut r = Vec::new(); 1527 writeln!( 1528 r, 1529 "#![allow(unused_imports)] 1530 #![allow(unused_variables)] 1531 #![allow(dead_code)] 1532 #![allow(unused_unit)] 1533 use {}{}::*; 1534 ", 1535 get_module_prefix(conf), 1536 conf.rust.interface_module 1537 )?; 1538 1539 for object in conf.objects.values() { 1540 write_rust_implementation_object(&mut r, object)?; 1541 } 1542 write_if_different(file, &r) 1543 } 1544 1545 /// Inspects the rust edition of the target crate to decide how the module 1546 /// imports should be written. 1547 /// 1548 /// As of Rust 2018, modules inside the crate should be prefixed with `crate::`. 1549 /// Prior to the 2018 edition, crate-local modules could be imported without 1550 /// this prefix. 1551 fn get_module_prefix(conf: &Config) -> &'static str { 1552 match conf.rust_edition { 1553 RustEdition::Rust2018 => "crate::", 1554 _ => "", 1555 } 1556 }