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 }