From c453828279575f3fa200b9c3c0a62a3441a4f0cb Mon Sep 17 00:00:00 2001 From: Leon Matthes Date: Wed, 24 Apr 2024 15:31:12 +0200 Subject: [PATCH] feat: lib: Serde support for QString See also: #943 --- crates/cxx-qt-lib/Cargo.toml | 2 + crates/cxx-qt-lib/src/core/qstring.rs | 23 +++++++++++ examples/qml_features/rust/Cargo.toml | 2 +- .../qml_features/rust/src/serialisation.rs | 38 +++---------------- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/crates/cxx-qt-lib/Cargo.toml b/crates/cxx-qt-lib/Cargo.toml index 2557f2e90..2eb118b99 100644 --- a/crates/cxx-qt-lib/Cargo.toml +++ b/crates/cxx-qt-lib/Cargo.toml @@ -22,6 +22,7 @@ http = { version = "1.0", optional = true } rgb = { version = "0.8", optional = true } time = { version = "0.3.20", optional = true } url = { version = "2.3", optional = true } +serde = { version = "1", features=["default", "derive"], optional = true } [build-dependencies] cxx-qt-build.workspace = true @@ -37,4 +38,5 @@ qt_gui = ["cxx-qt-lib-headers/qt_gui"] qt_qml = ["cxx-qt-lib-headers/qt_qml"] time = ["dep:time"] url = ["dep:url"] +serde = ["dep:serde"] link_qt_object_files = ["cxx-qt-build/link_qt_object_files"] diff --git a/crates/cxx-qt-lib/src/core/qstring.rs b/crates/cxx-qt-lib/src/core/qstring.rs index cc5dc3538..67d6856e0 100644 --- a/crates/cxx-qt-lib/src/core/qstring.rs +++ b/crates/cxx-qt-lib/src/core/qstring.rs @@ -191,10 +191,15 @@ mod ffi { } } +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + /// The QString class provides a Unicode character string. /// /// Note that QString is a UTF-16 whereas Rust strings are a UTF-8 #[repr(C)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(from = "String", into = "String"))] pub struct QString { /// The layout has changed between Qt 5 and Qt 6 /// @@ -293,6 +298,15 @@ impl From<&String> for QString { } } +impl From for QString { + /// Constructs a QString from a Rust string + /// + /// Note that this converts from UTF-8 to UTF-16 + fn from(str: String) -> Self { + ffi::qstring_init_from_rust_string(&str) + } +} + impl From<&QString> for String { /// Convert the QString to a Rust string /// @@ -302,6 +316,15 @@ impl From<&QString> for String { } } +impl From for String { + /// Convert the QString to a Rust string + /// + /// Note that this converts from UTF-16 to UTF-8 + fn from(qstring: QString) -> Self { + ffi::qstring_to_rust_string(&qstring) + } +} + impl QString { /// Returns a copy of this string with the lowest numbered place marker replaced by string a, i.e., %1, %2, ..., %99. pub fn arg(&self, a: &QString) -> Self { diff --git a/examples/qml_features/rust/Cargo.toml b/examples/qml_features/rust/Cargo.toml index 759df4bff..7fd57654e 100644 --- a/examples/qml_features/rust/Cargo.toml +++ b/examples/qml_features/rust/Cargo.toml @@ -16,7 +16,7 @@ crate-type = ["staticlib"] [dependencies] cxx.workspace = true cxx-qt.workspace = true -cxx-qt-lib.workspace = true +cxx-qt-lib = { workspace = true, features=["default", "serde"] } serde.workspace = true serde_json.workspace = true diff --git a/examples/qml_features/rust/src/serialisation.rs b/examples/qml_features/rust/src/serialisation.rs index 3504b59fe..969893a42 100644 --- a/examples/qml_features/rust/src/serialisation.rs +++ b/examples/qml_features/rust/src/serialisation.rs @@ -10,22 +10,6 @@ use serde::{Deserialize, Serialize}; -/// A struct representating our serialised form -#[derive(Deserialize, Serialize)] -pub struct DataSerde { - number: i32, - string: String, -} - -impl From<&SerialisationRust> for DataSerde { - fn from(value: &SerialisationRust) -> DataSerde { - DataSerde { - number: value.number, - string: value.string.to_string(), - } - } -} - /// A CXX-Qt bridge which shows how use serde for (de)serialization of the data in a QObjects' QPROPERTY's #[cxx_qt::bridge(cxx_file_stem = "serialisation")] pub mod qobject { @@ -63,6 +47,7 @@ use cxx_qt::CxxQtType; use cxx_qt_lib::QString; /// A QObject which can be serialised +#[derive(Serialize, Deserialize)] pub struct SerialisationRust { /// The number Q_PROPERTY pub number: i32, @@ -73,25 +58,14 @@ pub struct SerialisationRust { impl Default for SerialisationRust { fn default() -> Self { let string = r#"{"number": 4, "string": "Hello World!"}"#; - let data_serde: DataSerde = serde_json::from_str(string).unwrap(); - data_serde.into() - } -} - -impl From for SerialisationRust { - fn from(value: DataSerde) -> Self { - Self { - number: value.number, - string: QString::from(&value.string), - } + serde_json::from_str(string).unwrap() } } impl qobject::Serialisation { /// Retrieve the JSON form of this QObject pub fn as_json_str(self: Pin<&mut Self>) -> QString { - let data_serde = DataSerde::from(self.rust()); - match serde_json::to_string(&data_serde) { + match serde_json::to_string(&self.rust()) { Ok(data_string) => QString::from(&data_string), Err(err) => { self.error(QString::from(&err.to_string())); @@ -102,11 +76,11 @@ impl qobject::Serialisation { /// From a given JSON string try to load values for the Q_PROPERTYs // ANCHOR: book_grab_values - pub fn from_json_str(mut self: Pin<&mut Self>, string: &QString) { - match serde_json::from_str::(&string.to_string()) { + pub fn from_json_str(mut self: Pin<&mut Self>, qstring: &QString) { + match serde_json::from_str::(&qstring.to_string()) { Ok(data_serde) => { self.as_mut().set_number(data_serde.number); - self.as_mut().set_string(QString::from(&data_serde.string)); + self.as_mut().set_string(data_serde.string); } Err(err) => { self.error(QString::from(&err.to_string()));