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.
master
Jos van den Oever 2018-08-26 19:47:25 +02:00
parent ee5df0337b
commit 32fed925e9
9 changed files with 105 additions and 4 deletions

View File

@ -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;
}

View File

@ -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<F>(&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]

View File

@ -76,6 +76,7 @@ struct Property {
bool write;
bool optional;
bool rustByValue;
bool rustByFunction;
};
struct Argument {

View File

@ -22,6 +22,7 @@ pub struct Object {
optional_bytearray: Option<Vec<u8>>,
string: String,
optional_string: Option<String>,
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<F>(&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();
}
}

View File

@ -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<u64>);
fn string(&self) -> &str;
fn set_string(&mut self, value: String);
fn string_by_function<F>(&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()

View File

@ -24,6 +24,7 @@ private slots:
void testOptionalString();
void testByteArray();
void testOptionalByteArray();
void testStringByFunction();
};
template <typename V, typename Set, typename Get, typename Changed>
@ -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,

View File

@ -80,6 +80,11 @@
"type": "QByteArray",
"write": true,
"optional": true
},
"stringByFunction": {
"type": "QString",
"write": true,
"rustByFunction": true
}
}
}

View File

@ -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<const ushort*>(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<const ushort*>(v.data()), v.size());
}
quint16 Object::u16() const
{
return object_u16_get(m_d);

View File

@ -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();