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 }