From 32fed925e9ad79ad0df747b3c85cf326df0e5c6c Mon Sep 17 00:00:00 2001 From: Jos van den Oever Date: Sun, 26 Aug 2018 19:47:25 +0200 Subject: [PATCH] Intruduce rustByFunction rustByFunction lets a getter get a value even if it is not possible to return a value by reference. rustByFunction passes a getter function in the getter. This can be called with the value instead of returning a reference. --- src/parseJson.cpp | 1 + src/rust.cpp | 25 +++++++++++++-- src/structs.h | 1 + tests/rust_object_types/src/implementation.rs | 11 ++++++- tests/rust_object_types/src/interface.rs | 31 +++++++++++++++++++ tests/test_object_types.cpp | 13 ++++++++ tests/test_object_types.json | 5 +++ tests/test_object_types_rust.cpp | 18 ++++++++++- tests/test_object_types_rust.h | 4 +++ 9 files changed, 105 insertions(+), 4 deletions(-) diff --git a/src/parseJson.cpp b/src/parseJson.cpp index da9111a..f357cfe 100644 --- a/src/parseJson.cpp +++ b/src/parseJson.cpp @@ -178,6 +178,7 @@ parseProperty(const QString& name, const QJsonObject& json) { p.write = json.value("write").toBool(); p.optional = json.value("optional").toBool(); p.rustByValue = json.value("rustByValue").toBool(); + p.rustByFunction = json.value("rustByFunction").toBool(); return p; } diff --git a/src/rust.cpp b/src/rust.cpp index 6c4d0ac..a617809 100644 --- a/src/rust.cpp +++ b/src/rust.cpp @@ -331,7 +331,11 @@ pub trait %1Trait { r << QString(" fn %1(&self) -> &%2;\n").arg(lc, rustType(p)); r << QString(" fn %1_mut(&mut self) -> &mut %2;\n").arg(lc, rustType(p)); } else { - r << QString(" fn %1(&self) -> %2;\n").arg(lc, rustReturnType(p)); + if (p.rustByFunction) { + r << QString(" fn %1(&self, getter: F) where F: FnOnce(%2);").arg(lc, rustReturnType(p)); + } else { + r << QString(" fn %1(&self) -> %2;\n").arg(lc, rustReturnType(p)); + } if (p.write) { if (p.type.name == "QByteArray") { if (p.optional) { @@ -428,7 +432,23 @@ pub unsafe extern "C" fn %2_get(ptr: *mut %1) -> *mut %4 { )").arg(o.name, base, snakeCase(p.name), rustType(p)); } else if (p.type.isComplex() && !p.optional) { - r << QString(R"( + if (p.rustByFunction) { + r << QString(R"( +#[no_mangle] +pub extern "C" fn %2_get( + ptr: *const %1, + p: *mut %4, + set: fn(*mut %4, *const c_char, c_int), +) { + let o = unsafe { &*ptr }; + o.%3(|v| { + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, to_c_int(v.len())); + }); +} +)").arg(o.name, base, snakeCase(p.name), p.type.name); + } else { + r << QString(R"( #[no_mangle] pub extern "C" fn %2_get( ptr: *const %1, @@ -441,6 +461,7 @@ pub extern "C" fn %2_get( set(p, s, to_c_int(v.len())); } )").arg(o.name, base, snakeCase(p.name), p.type.name); + } if (p.write && p.type.name == "QString") { r << QString(R"( #[no_mangle] diff --git a/src/structs.h b/src/structs.h index fcc9139..862451d 100644 --- a/src/structs.h +++ b/src/structs.h @@ -76,6 +76,7 @@ struct Property { bool write; bool optional; bool rustByValue; + bool rustByFunction; }; struct Argument { diff --git a/tests/rust_object_types/src/implementation.rs b/tests/rust_object_types/src/implementation.rs index e02cb35..b6c76a8 100644 --- a/tests/rust_object_types/src/implementation.rs +++ b/tests/rust_object_types/src/implementation.rs @@ -22,6 +22,7 @@ pub struct Object { optional_bytearray: Option>, string: String, optional_string: Option, + string_by_function: String, } impl ObjectTrait for Object { @@ -44,7 +45,8 @@ impl ObjectTrait for Object { bytearray: Vec::new(), optional_bytearray: None, string: String::new(), - optional_string: None + optional_string: None, + string_by_function: String::new() } } fn emit(&self) -> &ObjectEmitter { @@ -179,5 +181,12 @@ impl ObjectTrait for Object { self.string = value; self.emit.string_changed(); } + fn string_by_function(&self, getter: F) where F: FnOnce(&str) { + getter(&self.string_by_function) + } + fn set_string_by_function(&mut self, value: String) { + self.string_by_function = value; + self.emit.string_by_function_changed(); + } } diff --git a/tests/rust_object_types/src/interface.rs b/tests/rust_object_types/src/interface.rs index 49c65e3..96ec458 100644 --- a/tests/rust_object_types/src/interface.rs +++ b/tests/rust_object_types/src/interface.rs @@ -87,6 +87,7 @@ pub struct ObjectEmitter { optional_string_changed: fn(*const ObjectQObject), optional_u64_changed: fn(*const ObjectQObject), string_changed: fn(*const ObjectQObject), + string_by_function_changed: fn(*const ObjectQObject), u16_changed: fn(*const ObjectQObject), u32_changed: fn(*const ObjectQObject), u64_changed: fn(*const ObjectQObject), @@ -177,6 +178,12 @@ impl ObjectEmitter { (self.string_changed)(ptr); } } + pub fn string_by_function_changed(&self) { + let ptr = *self.qobject.lock().unwrap(); + if !ptr.is_null() { + (self.string_by_function_changed)(ptr); + } + } pub fn u16_changed(&self) { let ptr = *self.qobject.lock().unwrap(); if !ptr.is_null() { @@ -232,6 +239,7 @@ pub trait ObjectTrait { fn set_optional_u64(&mut self, value: Option); fn string(&self) -> &str; fn set_string(&mut self, value: String); + fn string_by_function(&self, getter: F) where F: FnOnce(&str); fn set_string_by_function(&mut self, value: String); fn u16(&self) -> u16; fn set_u16(&mut self, value: u16); fn u32(&self) -> u32; @@ -258,6 +266,7 @@ pub extern "C" fn object_new( object_optional_string_changed: fn(*const ObjectQObject), object_optional_u64_changed: fn(*const ObjectQObject), object_string_changed: fn(*const ObjectQObject), + object_string_by_function_changed: fn(*const ObjectQObject), object_u16_changed: fn(*const ObjectQObject), object_u32_changed: fn(*const ObjectQObject), object_u64_changed: fn(*const ObjectQObject), @@ -278,6 +287,7 @@ pub extern "C" fn object_new( optional_string_changed: object_optional_string_changed, optional_u64_changed: object_optional_u64_changed, string_changed: object_string_changed, + string_by_function_changed: object_string_by_function_changed, u16_changed: object_u16_changed, u32_changed: object_u32_changed, u64_changed: object_u64_changed, @@ -494,6 +504,27 @@ pub extern "C" fn object_string_set(ptr: *mut Object, v: *const c_ushort, len: c o.set_string(s); } +#[no_mangle] +pub extern "C" fn object_string_by_function_get( + ptr: *const Object, + p: *mut QString, + set: fn(*mut QString, *const c_char, c_int), +) { + let o = unsafe { &*ptr }; + o.string_by_function(|v| { + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, to_c_int(v.len())); + }); +} + +#[no_mangle] +pub extern "C" fn object_string_by_function_set(ptr: *mut Object, v: *const c_ushort, len: c_int) { + let o = unsafe { &mut *ptr }; + let mut s = String::new(); + set_string_from_utf16(&mut s, v, len); + o.set_string_by_function(s); +} + #[no_mangle] pub unsafe extern "C" fn object_u16_get(ptr: *const Object) -> u16 { (&*ptr).u16() diff --git a/tests/test_object_types.cpp b/tests/test_object_types.cpp index 8278f36..0b14786 100644 --- a/tests/test_object_types.cpp +++ b/tests/test_object_types.cpp @@ -24,6 +24,7 @@ private slots: void testOptionalString(); void testByteArray(); void testOptionalByteArray(); + void testStringByFunction(); }; template @@ -208,6 +209,18 @@ void TestRustObjectTypes::testString() &Object::string, &Object::stringChanged); } +void TestRustObjectTypes::testStringByFunction() +{ + testSetter(QString(), &Object::setStringByFunction, + &Object::stringByFunction, &Object::stringByFunctionChanged); + testSetter(QString(""), &Object::setStringByFunction, + &Object::stringByFunction, &Object::stringByFunctionChanged); + testSetter(QString("Konqi"), &Object::setStringByFunction, + &Object::stringByFunction, &Object::stringByFunctionChanged); + testSetter(QString("$𐐷𤭢"), &Object::setStringByFunction, + &Object::stringByFunction, &Object::stringByFunctionChanged); +} + void TestRustObjectTypes::testOptionalString() { testSetter(QString(), &Object::setOptionalString, diff --git a/tests/test_object_types.json b/tests/test_object_types.json index ebb368c..fc75401 100644 --- a/tests/test_object_types.json +++ b/tests/test_object_types.json @@ -80,6 +80,11 @@ "type": "QByteArray", "write": true, "optional": true + }, + "stringByFunction": { + "type": "QString", + "write": true, + "rustByFunction": true } } } diff --git a/tests/test_object_types_rust.cpp b/tests/test_object_types_rust.cpp index 6b9523c..91b28f6 100644 --- a/tests/test_object_types_rust.cpp +++ b/tests/test_object_types_rust.cpp @@ -95,6 +95,10 @@ namespace { { emit o->stringChanged(); } + inline void objectStringByFunctionChanged(Object* o) + { + emit o->stringByFunctionChanged(); + } inline void objectU16Changed(Object* o) { emit o->u16Changed(); @@ -113,7 +117,7 @@ namespace { } } extern "C" { - Object::Private* object_new(Object*, void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*)); + Object::Private* object_new(Object*, void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*), void (*)(Object*)); void object_free(Object::Private*); bool object_boolean_get(const Object::Private*); void object_boolean_set(Object::Private*, bool); @@ -145,6 +149,8 @@ extern "C" { void object_optional_u64_set_none(Object::Private*); void object_string_get(const Object::Private*, QString*, qstring_set); void object_string_set(Object::Private*, const ushort *str, int len); + void object_string_by_function_get(const Object::Private*, QString*, qstring_set); + void object_string_by_function_set(Object::Private*, const ushort *str, int len); quint16 object_u16_get(const Object::Private*); void object_u16_set(Object::Private*, quint16); quint32 object_u32_get(const Object::Private*); @@ -178,6 +184,7 @@ Object::Object(QObject *parent): objectOptionalStringChanged, objectOptionalU64Changed, objectStringChanged, + objectStringByFunctionChanged, objectU16Changed, objectU32Changed, objectU64Changed, @@ -316,6 +323,15 @@ QString Object::string() const void Object::setString(const QString& v) { object_string_set(m_d, reinterpret_cast(v.data()), v.size()); } +QString Object::stringByFunction() const +{ + QString v; + object_string_by_function_get(m_d, &v, set_qstring); + return v; +} +void Object::setStringByFunction(const QString& v) { + object_string_by_function_set(m_d, reinterpret_cast(v.data()), v.size()); +} quint16 Object::u16() const { return object_u16_get(m_d); diff --git a/tests/test_object_types_rust.h b/tests/test_object_types_rust.h index 69b1863..fd40f43 100644 --- a/tests/test_object_types_rust.h +++ b/tests/test_object_types_rust.h @@ -28,6 +28,7 @@ private: Q_PROPERTY(QString optionalString READ optionalString WRITE setOptionalString NOTIFY optionalStringChanged FINAL) Q_PROPERTY(QVariant optionalU64 READ optionalU64 WRITE setOptionalU64 NOTIFY optionalU64Changed FINAL) Q_PROPERTY(QString string READ string WRITE setString NOTIFY stringChanged FINAL) + Q_PROPERTY(QString stringByFunction READ stringByFunction WRITE setStringByFunction NOTIFY stringByFunctionChanged FINAL) Q_PROPERTY(quint16 u16 READ u16 WRITE setU16 NOTIFY u16Changed FINAL) Q_PROPERTY(quint32 u32 READ u32 WRITE setU32 NOTIFY u32Changed FINAL) Q_PROPERTY(quint64 u64 READ u64 WRITE setU64 NOTIFY u64Changed FINAL) @@ -62,6 +63,8 @@ public: void setOptionalU64(const QVariant& v); QString string() const; void setString(const QString& v); + QString stringByFunction() const; + void setStringByFunction(const QString& v); quint16 u16() const; void setU16(quint16 v); quint32 u32() const; @@ -84,6 +87,7 @@ signals: void optionalStringChanged(); void optionalU64Changed(); void stringChanged(); + void stringByFunctionChanged(); void u16Changed(); void u32Changed(); void u64Changed();