diff --git a/README.md b/README.md index 3d6d1e5..c9a5785 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,87 @@ -# Rust Qt Bindings Generator +# Rust Qt Binding Generator -![Rust Qt Bindings](logo.svg) +![Rust Qt Binding](logo.svg) -This generator gets you started quickly to use Rust code from Qt and QML. +This code generator gets you started quickly to use Rust code from Qt and QML. In other words, it helps to create a Qt based GUI on top of Rust code. + +Qt is a mature cross-platform graphical user interface library. Rust is a new programming language with strong compile time checks and a modern syntax. + +To combine Qt and Rust, write an interface in a JSON file. From that, the generator creates Qt code and Rust code. The Qt code can be used directly. The Rust code has two files: interface and implementation. The interface can be used directly. + +```json +{ + "cppFile": "src/person.cpp", + "rust": { + "dir": "rust", + "interfaceModule": "interface", + "implementationModule": "implementation" + }, + "objects": { + "Person": { + "type": "Object", + "properties": { + "name": { + "type": "QString", + "write": true + } + } + } + } +} +``` + +This file describes an binding with one object, `Person`. `Person` has one property: `name`. It is a writable property. + +The Rust Qt Binding Generator will create binding source code from this description: + +```bash +rust_qt_binding_generator binding.json +``` + +This will create four files: + +* *src/person.h* +* *src/person.cpp* +* rust/src/implemenation.rs +* *rust/src/interface.rs* + +Only `implementation.rs` should be changed. The other files are the binding. `implementation.rs` is initialy created with a simple implementation that is shown here with some comments. + +```rust +use interface::*; + +/// A Person +pub struct Person { + /// Emit signals the the Qt code. + emit: PersonEmitter, + /// The name of the person. + name: String, +} + +/// Implementation of the binding +impl PersonTrait for Person { + /// Create a new person with default data. + fn create(emit: PersonEmitter) -> Person { + Person { + emit: emit, + name: String::new(), + } + } + /// The emitter can emit signals to the Qt code. + fn emit(&self) -> &PersonEmitter { + &self.emit + } + /// Get the name of the Person + fn get_name(&self) -> String { + self.name.clone() + } + /// Set the name of the Person + fn set_name(&mut self, value: String) { + self.name = value; + self.emit.name_changed(); + } +} +``` The building block of Qt and QML projects are QObject and the Model View classes. `rust_qt_binding_generator` reads a json file to generate QObject or QAbstractItemModel classes that call into generated Rust files. For each type from the JSON file, a Rust trait is generated that should be implemented. diff --git a/demo/processes.json b/demo/processes.json index 59cdc6c..ee2c816 100644 --- a/demo/processes.json +++ b/demo/processes.json @@ -38,7 +38,8 @@ "type": "quint8" }, "cmd": { - "type": "QString" + "type": "QString", + "rustByValue": true } } } diff --git a/demo/rust/src/implementation.rs b/demo/rust/src/implementation.rs index 52d17a9..774e939 100644 --- a/demo/rust/src/implementation.rs +++ b/demo/rust/src/implementation.rs @@ -13,6 +13,7 @@ pub struct DirEntry { name: OsString, metadata: Option, path: Option, + icon: Vec, } type Incoming = Arc>>>; @@ -23,6 +24,7 @@ impl Item for DirEntry { name: OsString::from(name), metadata: metadata(name).ok(), path: None, + icon: Vec::new() } } fn can_fetch_more(&self) -> bool { @@ -43,6 +45,9 @@ impl Item for DirEntry { fn file_size(&self) -> Option { self.metadata.as_ref().map(|m| m.len()) } + fn icon(&self) -> &[u8] { + &self.icon + } fn retrieve(id: usize, parents: Vec<&DirEntry>, q: Incoming, emit: TreeEmitter) { let mut v = Vec::new(); let path: PathBuf = parents.into_iter().map(|e| &e.name).collect(); @@ -53,6 +58,7 @@ impl Item for DirEntry { name: i.file_name(), metadata: i.metadata().ok(), path: Some(i.path()), + icon: Vec::new(), }; v.push(de); } @@ -73,6 +79,7 @@ impl Default for DirEntry { name: OsString::new(), metadata: None, path: None, + icon: Vec::new(), } } } @@ -86,6 +93,7 @@ pub trait Item: Default { fn file_permissions(&self) -> i32; fn file_type(&self) -> i32; fn file_size(&self) -> Option; + fn icon(&self) -> &[u8]; } pub type Tree = RGeneralItemModel; @@ -195,8 +203,8 @@ where fn emit(&self) -> &TreeEmitter { &self.emit } - fn get_path(&self) -> Option { - self.path.clone() + fn get_path(&self) -> Option<&str> { + self.path.as_ref().map(|s|&s[..]) } fn set_path(&mut self, value: Option) { if self.path != value { @@ -261,8 +269,8 @@ where self.get(item).data.file_permissions() } #[allow(unused_variables)] - fn file_icon(&self, item: usize) -> Vec { - Vec::new() + fn file_icon(&self, item: usize) -> &[u8] { + self.get(item).data.icon() } fn file_path(&self, item: usize) -> Option { self.get(item).data.file_path() diff --git a/demo/rust/src/interface.rs b/demo/rust/src/interface.rs index 74316f2..53fb74c 100644 --- a/demo/rust/src/interface.rs +++ b/demo/rust/src/interface.rs @@ -55,6 +55,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -78,8 +87,8 @@ impl QByteArray { } } -impl<'a> From<&'a Vec> for QByteArray { - fn from(value: &'a Vec) -> QByteArray { +impl<'a> From<&'a [u8]> for QByteArray { + fn from(value: &'a [u8]) -> QByteArray { QByteArray { len: value.len() as c_int, data: value.as_ptr(), @@ -167,7 +176,7 @@ impl TreeUniformTree { pub trait TreeTrait { fn create(emit: TreeEmitter, model: TreeUniformTree) -> Self; fn emit(&self) -> &TreeEmitter; - fn get_path(&self) -> Option; + fn get_path(&self) -> Option<&str>; fn set_path(&mut self, value: Option); fn row_count(&self, Option) -> usize; fn can_fetch_more(&self, Option) -> bool { @@ -178,7 +187,7 @@ pub trait TreeTrait { fn index(&self, item: Option, row: usize) -> usize; fn parent(&self, item: usize) -> Option; fn row(&self, item: usize) -> usize; - fn file_icon(&self, item: usize) -> Vec; + fn file_icon(&self, item: usize) -> &[u8]; fn file_name(&self, item: usize) -> String; fn file_path(&self, item: usize) -> Option; fn file_permissions(&self, item: usize) -> i32; @@ -231,7 +240,7 @@ pub unsafe extern "C" fn tree_path_get( ) { let data = (&*ptr).get_path(); if let Some(data) = data { - set(p, QString::from(&data)); + set(p, data.into()); } } @@ -323,7 +332,7 @@ pub unsafe extern "C" fn tree_data_file_icon( set: fn(*mut c_void, QByteArray), ) { let data = (&*ptr).file_icon(item); - set(d, QByteArray::from(&data)); + set(d, (data).into()); } #[no_mangle] @@ -333,7 +342,7 @@ pub unsafe extern "C" fn tree_data_file_name( set: fn(*mut c_void, QString), ) { let data = (&*ptr).file_name(item); - set(d, QString::from(&data)); + set(d, (&data).into()); } #[no_mangle] diff --git a/demo/rust/src/processes_implementation.rs b/demo/rust/src/processes_implementation.rs index 4ad75cb..ac1ca88 100644 --- a/demo/rust/src/processes_implementation.rs +++ b/demo/rust/src/processes_implementation.rs @@ -361,8 +361,8 @@ impl ProcessesTrait for Processes { fn memory(&self, item: usize) -> u64 { self.process(item).memory } - fn name(&self, item: usize) -> String { - self.process(item).name.clone() + fn name(&self, item: usize) -> &str { + &self.process(item).name } fn cmd(&self, item: usize) -> String { self.process(item).cmd.join(" ") diff --git a/demo/rust/src/processes_interface.rs b/demo/rust/src/processes_interface.rs index ae4e35a..eb90df9 100644 --- a/demo/rust/src/processes_interface.rs +++ b/demo/rust/src/processes_interface.rs @@ -55,6 +55,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -159,7 +168,7 @@ pub trait ProcessesTrait { fn cpu_percentage(&self, item: usize) -> u8; fn cpu_usage(&self, item: usize) -> f32; fn memory(&self, item: usize) -> u64; - fn name(&self, item: usize) -> String; + fn name(&self, item: usize) -> &str; fn pid(&self, item: usize) -> u32; fn uid(&self, item: usize) -> u32; } @@ -290,7 +299,7 @@ pub unsafe extern "C" fn processes_data_cmd( set: fn(*mut c_void, QString), ) { let data = (&*ptr).cmd(item); - set(d, QString::from(&data)); + set(d, (&data).into()); } #[no_mangle] @@ -315,7 +324,7 @@ pub unsafe extern "C" fn processes_data_name( set: fn(*mut c_void, QString), ) { let data = (&*ptr).name(item); - set(d, QString::from(&data)); + set(d, (data).into()); } #[no_mangle] diff --git a/demo/tree.json b/demo/tree.json index e5db5f6..0085cdc 100644 --- a/demo/tree.json +++ b/demo/tree.json @@ -18,7 +18,8 @@ "itemProperties": { "fileName": { "type": "QString", - "roles": [ ["display"] ] + "roles": [ ["display"] ], + "rustByValue": true }, "fileIcon": { "type": "QByteArray", @@ -32,7 +33,8 @@ "filePath": { "type": "QString", "optional": true, - "roles": [ [], [], ["display"] ] + "roles": [ [], [], ["display"] ], + "rustByValue": true }, "filePermissions": { "type": "qint32", diff --git a/src/parseJson.cpp b/src/parseJson.cpp index 5141099..2b56420 100644 --- a/src/parseJson.cpp +++ b/src/parseJson.cpp @@ -12,7 +12,7 @@ BindingTypeProperties simpleType(BindingType type, const char* name, const char* .cppSetType = name, .cSetType = name, .rustType = name, - .rustTypeInit = init, + .rustTypeInit = init }; } @@ -105,6 +105,7 @@ parseProperty(const QString& name, const QJsonObject& json) { p.type = parseBindingType(json.value("type").toString()); p.write = json.value("write").toBool(); p.optional = json.value("optional").toBool(); + p.rustByValue = json.value("rustByValue").toBool(); return p; } @@ -129,6 +130,7 @@ parseItemProperty(const QString& name, const QJsonObject& json) { ip.type = parseBindingType(json.value("type").toString()); ip.write = json.value("write").toBool(); ip.optional = json.value("optional").toBool(); + ip.rustByValue = json.value("rustByValue").toBool(); QJsonArray roles = json.value("roles").toArray(); for (auto r: roles) { QList l; diff --git a/src/rust.cpp b/src/rust.cpp index 0355f0c..daa9ed2 100644 --- a/src/rust.cpp +++ b/src/rust.cpp @@ -10,6 +10,25 @@ QString rustType(const T& p) return p.type.rustType; } +template +QString rustReturnType(const T& p) +{ + QString type = p.type.rustType; + if (type == "String" && !p.rustByValue) { + type = "str"; + } + if (type == "Vec" && !p.rustByValue) { + type = "[u8]"; + } + if (p.type.isComplex() && !p.rustByValue) { + type = "&" + type; + } + if (p.optional) { + return "Option<" + type + ">"; + } + return type; +} + template QString rustCType(const T& p) { @@ -235,7 +254,7 @@ pub trait %1Trait { r << QString(" fn get_%1(&self) -> &%2;\n").arg(lc, rustType(p)); r << QString(" fn get_mut_%1(&mut self) -> &mut %2;\n").arg(lc, rustType(p)); } else { - r << QString(" fn get_%1(&self) -> %2;\n").arg(lc, rustType(p)); + r << QString(" fn get_%1(&self) -> %2;\n").arg(lc, rustReturnType(p)); if (p.write) { r << QString(" fn set_%1(&mut self, value: %2);\n").arg(lc, rustType(p)); } @@ -264,7 +283,7 @@ pub trait %1Trait { if (o.type != ObjectType::Object) { for (auto ip: o.itemProperties) { r << QString(" fn %1(&self, item: usize) -> %2;\n") - .arg(snakeCase(ip.name), rustType(ip)); + .arg(snakeCase(ip.name), rustReturnType(ip)); if (ip.write) { r << QString(" fn set_%1(&mut self, item: usize, %2) -> bool;\n") .arg(snakeCase(ip.name), rustType(ip)); @@ -308,9 +327,10 @@ pub unsafe extern "C" fn %2_get( set: fn(*mut c_void, %4), ) { let data = (&*ptr).get_%3(); - set(p, %4::from(&data)); + set(p, %5data.into()); } -)").arg(o.name, base, snakeCase(p.name), p.type.name); +)").arg(o.name, base, snakeCase(p.name), p.type.name, + p.rustByValue ?"&" :""); if (p.write) { const QString type = p.type.name == "QString" ? "QStringIn" : p.type.name; r << QString(R"( @@ -330,10 +350,11 @@ pub unsafe extern "C" fn %2_get( ) { let data = (&*ptr).get_%3(); if let Some(data) = data { - set(p, %4::from(&data)); + set(p, %5data.into()); } } -)").arg(o.name, base, snakeCase(p.name), p.type.name); +)").arg(o.name, base, snakeCase(p.name), p.type.name, + p.rustByValue ?"&" :""); if (p.write) { const QString type = p.type.name == "QString" ? "QStringIn" : p.type.name; r << QString(R"( @@ -479,9 +500,10 @@ pub unsafe extern "C" fn %2_data_%3( set: fn(*mut c_void, %4), ) { let data = (&*ptr).%3(%6); - set(d, %4::from(&data)); + set(d, (%7data).into()); } -)").arg(o.name, lcname, snakeCase(ip.name), ip.type.name, indexDecl, index); +)").arg(o.name, lcname, snakeCase(ip.name), ip.type.name, indexDecl, index, + ip.rustByValue ?"&" :""); } else if (ip.type.isComplex()) { r << QString(R"( #[no_mangle] @@ -616,6 +638,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -642,8 +673,8 @@ impl QByteArray { } } -impl<'a> From<&'a Vec> for QByteArray { - fn from(value: &'a Vec) -> QByteArray { +impl<'a> From<&'a [u8]> for QByteArray { + fn from(value: &'a [u8]) -> QByteArray { QByteArray { len: value.len() as c_int, data: value.as_ptr(), @@ -760,11 +791,21 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) { fn get_mut_%1(&mut self) -> &mut %2 { &mut self.%1 } -)").arg(lc, rustType(p)); +)").arg(lc, rustReturnType(p)); } else { - r << QString(" fn get_%1(&self) -> %2 {\n").arg(lc, rustType(p)); + r << QString(" fn get_%1(&self) -> %2 {\n").arg(lc, rustReturnType(p)); if (p.type.isComplex()) { - r << QString(" self.%1.clone()\n").arg(lc); + if (p.optional) { +/* + if (rustType(p) == "Option") { + r << QString(" self.%1.as_ref().map(|p|p.as_str())\n").arg(lc); + } else { + } +*/ + r << QString(" self.%1.as_ref().map(|p|&p[..])\n").arg(lc); + } else { + r << QString(" &self.%1\n").arg(lc); + } } else { r << QString(" self.%1\n").arg(lc); } @@ -803,8 +844,12 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) { for (auto ip: o.itemProperties) { const QString lc(snakeCase(ip.name)); r << QString(" fn %1(&self, item: usize) -> %2 {\n") - .arg(lc, rustType(ip)); - r << " self.list[item]." << lc << ".clone()\n"; + .arg(lc, rustReturnType(ip)); + if (ip.type.isComplex()) { + r << " &self.list[item]." << lc << "\n"; + } else { + r << " self.list[item]." << lc << "\n"; + } r << " }\n"; if (ip.write) { r << QString(" fn set_%1(&mut self, item: usize, v: %2) -> bool {\n") diff --git a/src/structs.h b/src/structs.h index ded3783..80c4d34 100644 --- a/src/structs.h +++ b/src/structs.h @@ -41,6 +41,7 @@ struct Property { BindingTypeProperties type; bool write; bool optional; + bool rustByValue; }; struct ItemProperty { @@ -48,6 +49,7 @@ struct ItemProperty { BindingTypeProperties type; bool write; bool optional; + bool rustByValue; QList> roles; }; diff --git a/tests/rust_list/src/implementation.rs b/tests/rust_list/src/implementation.rs index 2ea08d8..867b8a2 100644 --- a/tests/rust_list/src/implementation.rs +++ b/tests/rust_list/src/implementation.rs @@ -28,8 +28,8 @@ impl PersonsTrait for Persons { fn row_count(&self) -> usize { self.list.len() } - fn user_name(&self, item: usize) -> String { - self.list[item].user_name.clone() + fn user_name(&self, item: usize) -> &str { + &self.list[item].user_name } fn set_user_name(&mut self, item: usize, v: String) -> bool { self.list[item].user_name = v; diff --git a/tests/rust_list/src/interface.rs b/tests/rust_list/src/interface.rs index 147f231..81b85a7 100644 --- a/tests/rust_list/src/interface.rs +++ b/tests/rust_list/src/interface.rs @@ -55,6 +55,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -143,7 +152,7 @@ pub trait PersonsTrait { } fn fetch_more(&mut self) {} fn sort(&mut self, u8, SortOrder) {} - fn user_name(&self, item: usize) -> String; + fn user_name(&self, item: usize) -> &str; fn set_user_name(&mut self, item: usize, String) -> bool; } @@ -210,7 +219,7 @@ pub unsafe extern "C" fn persons_data_user_name( set: fn(*mut c_void, QString), ) { let data = (&*ptr).user_name(row as usize); - set(d, QString::from(&data)); + set(d, (data).into()); } #[no_mangle] diff --git a/tests/rust_object/src/implementation.rs b/tests/rust_object/src/implementation.rs index 867f7fe..7880813 100644 --- a/tests/rust_object/src/implementation.rs +++ b/tests/rust_object/src/implementation.rs @@ -18,8 +18,8 @@ impl PersonTrait for Person { fn emit(&self) -> &PersonEmitter { &self.emit } - fn get_user_name(&self) -> String { - self.user_name.clone() + fn get_user_name(&self) -> &str { + &self.user_name } fn set_user_name(&mut self, value: String) { self.user_name = value; diff --git a/tests/rust_object/src/interface.rs b/tests/rust_object/src/interface.rs index e5b9fb1..1642eb6 100644 --- a/tests/rust_object/src/interface.rs +++ b/tests/rust_object/src/interface.rs @@ -29,6 +29,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -63,7 +72,7 @@ impl PersonEmitter { pub trait PersonTrait { fn create(emit: PersonEmitter) -> Self; fn emit(&self) -> &PersonEmitter; - fn get_user_name(&self) -> String; + fn get_user_name(&self) -> &str; fn set_user_name(&mut self, value: String); } @@ -92,7 +101,7 @@ pub unsafe extern "C" fn person_user_name_get( set: fn(*mut c_void, QString), ) { let data = (&*ptr).get_user_name(); - set(p, QString::from(&data)); + set(p, data.into()); } #[no_mangle] diff --git a/tests/rust_object_types/src/implementation.rs b/tests/rust_object_types/src/implementation.rs index d5cc0ae..d64d07c 100644 --- a/tests/rust_object_types/src/implementation.rs +++ b/tests/rust_object_types/src/implementation.rs @@ -39,8 +39,8 @@ impl ObjectTrait for Object { self.boolean = value; self.emit.boolean_changed(); } - fn get_bytearray(&self) -> Vec { - self.bytearray.clone() + fn get_bytearray(&self) -> &[u8] { + &self.bytearray } fn set_bytearray(&mut self, value: Vec) { self.bytearray = value; @@ -53,22 +53,22 @@ impl ObjectTrait for Object { self.integer = value; self.emit.integer_changed(); } - fn get_optional_bytearray(&self) -> Option> { - self.optional_bytearray.clone() + fn get_optional_bytearray(&self) -> Option<&[u8]> { + self.optional_bytearray.as_ref().map(|p|&p[..]) } fn set_optional_bytearray(&mut self, value: Option>) { self.optional_bytearray = value; self.emit.optional_bytearray_changed(); } - fn get_optional_string(&self) -> Option { - self.optional_string.clone() + fn get_optional_string(&self) -> Option<&str> { + self.optional_string.as_ref().map(|p|&p[..]) } fn set_optional_string(&mut self, value: Option) { self.optional_string = value; self.emit.optional_string_changed(); } - fn get_string(&self) -> String { - self.string.clone() + fn get_string(&self) -> &str { + &self.string } fn set_string(&mut self, value: String) { self.string = value; diff --git a/tests/rust_object_types/src/interface.rs b/tests/rust_object_types/src/interface.rs index 9e42e87..989899b 100644 --- a/tests/rust_object_types/src/interface.rs +++ b/tests/rust_object_types/src/interface.rs @@ -55,6 +55,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -78,8 +87,8 @@ impl QByteArray { } } -impl<'a> From<&'a Vec> for QByteArray { - fn from(value: &'a Vec) -> QByteArray { +impl<'a> From<&'a [u8]> for QByteArray { + fn from(value: &'a [u8]) -> QByteArray { QByteArray { len: value.len() as c_int, data: value.as_ptr(), @@ -163,15 +172,15 @@ pub trait ObjectTrait { fn emit(&self) -> &ObjectEmitter; fn get_boolean(&self) -> bool; fn set_boolean(&mut self, value: bool); - fn get_bytearray(&self) -> Vec; + fn get_bytearray(&self) -> &[u8]; fn set_bytearray(&mut self, value: Vec); fn get_integer(&self) -> i32; fn set_integer(&mut self, value: i32); - fn get_optional_bytearray(&self) -> Option>; + fn get_optional_bytearray(&self) -> Option<&[u8]>; fn set_optional_bytearray(&mut self, value: Option>); - fn get_optional_string(&self) -> Option; + fn get_optional_string(&self) -> Option<&str>; fn set_optional_string(&mut self, value: Option); - fn get_string(&self) -> String; + fn get_string(&self) -> &str; fn set_string(&mut self, value: String); fn get_u64(&self) -> u64; fn set_u64(&mut self, value: u64); @@ -228,7 +237,7 @@ pub unsafe extern "C" fn object_bytearray_get( set: fn(*mut c_void, QByteArray), ) { let data = (&*ptr).get_bytearray(); - set(p, QByteArray::from(&data)); + set(p, data.into()); } #[no_mangle] @@ -254,7 +263,7 @@ pub unsafe extern "C" fn object_optional_bytearray_get( ) { let data = (&*ptr).get_optional_bytearray(); if let Some(data) = data { - set(p, QByteArray::from(&data)); + set(p, data.into()); } } @@ -275,7 +284,7 @@ pub unsafe extern "C" fn object_optional_string_get( ) { let data = (&*ptr).get_optional_string(); if let Some(data) = data { - set(p, QString::from(&data)); + set(p, data.into()); } } @@ -295,7 +304,7 @@ pub unsafe extern "C" fn object_string_get( set: fn(*mut c_void, QString), ) { let data = (&*ptr).get_string(); - set(p, QString::from(&data)); + set(p, data.into()); } #[no_mangle] diff --git a/tests/rust_objects/src/implementation.rs b/tests/rust_objects/src/implementation.rs index c4f1035..d3186d4 100644 --- a/tests/rust_objects/src/implementation.rs +++ b/tests/rust_objects/src/implementation.rs @@ -41,8 +41,8 @@ impl InnerObjectTrait for InnerObject { fn emit(&self) -> &InnerObjectEmitter { &self.emit } - fn get_description(&self) -> String { - self.description.clone() + fn get_description(&self) -> &str { + &self.description } fn set_description(&mut self, value: String) { self.description = value; diff --git a/tests/rust_objects/src/interface.rs b/tests/rust_objects/src/interface.rs index 15bfcd4..5dd9bdf 100644 --- a/tests/rust_objects/src/interface.rs +++ b/tests/rust_objects/src/interface.rs @@ -29,6 +29,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -121,7 +130,7 @@ impl InnerObjectEmitter { pub trait InnerObjectTrait { fn create(emit: InnerObjectEmitter) -> Self; fn emit(&self) -> &InnerObjectEmitter; - fn get_description(&self) -> String; + fn get_description(&self) -> &str; fn set_description(&mut self, value: String); } @@ -150,7 +159,7 @@ pub unsafe extern "C" fn inner_object_description_get( set: fn(*mut c_void, QString), ) { let data = (&*ptr).get_description(); - set(p, QString::from(&data)); + set(p, data.into()); } #[no_mangle] diff --git a/tests/rust_tree/src/implementation.rs b/tests/rust_tree/src/implementation.rs index 5cacf1a..0c1c3e9 100644 --- a/tests/rust_tree/src/implementation.rs +++ b/tests/rust_tree/src/implementation.rs @@ -37,8 +37,8 @@ impl PersonsTrait for Persons { fn row(&self, item: usize) -> usize { item } - fn user_name(&self, item: usize) -> String { - self.list[item].user_name.clone() + fn user_name(&self, item: usize) -> &str { + &self.list[item].user_name } fn set_user_name(&mut self, item: usize, v: String) -> bool { self.list[item].user_name = v; diff --git a/tests/rust_tree/src/interface.rs b/tests/rust_tree/src/interface.rs index 0462cfb..d3dbc2e 100644 --- a/tests/rust_tree/src/interface.rs +++ b/tests/rust_tree/src/interface.rs @@ -55,6 +55,15 @@ impl QStringIn { } } +impl<'a> From<&'a str> for QString { + fn from(string: &'a str) -> QString { + QString { + len: string.len() as c_int, + data: string.as_ptr(), + } + } +} + impl<'a> From<&'a String> for QString { fn from(string: &'a String) -> QString { QString { @@ -146,7 +155,7 @@ pub trait PersonsTrait { fn index(&self, item: Option, row: usize) -> usize; fn parent(&self, item: usize) -> Option; fn row(&self, item: usize) -> usize; - fn user_name(&self, item: usize) -> String; + fn user_name(&self, item: usize) -> &str; fn set_user_name(&mut self, item: usize, String) -> bool; } @@ -264,7 +273,7 @@ pub unsafe extern "C" fn persons_data_user_name( set: fn(*mut c_void, QString), ) { let data = (&*ptr).user_name(item); - set(d, QString::from(&data)); + set(d, (data).into()); } #[no_mangle]