Skip to content

Commit

Permalink
feat: lib: Serde support for QString (KDAB#944)
Browse files Browse the repository at this point in the history
See also: KDAB#943

Co-authored-by: Montel Laurent <laurent.montel@kdab.com>
  • Loading branch information
LeonMatthesKDAB and Montel authored May 10, 2024
1 parent add14e0 commit fdb5100
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `c_void` in CXX-Qt-lib for easy access to `void *`
- `CxxQtThread` is now marked as `Sync` so that it can be used by reference
- Add cxx-qt-lib-extras crate which contains: `QCommandLineOption`, `QCommandLineParser`, `QElapsedTimer`, `QApplication`
- Serde support for `QString` (requires "serde" feature on cxx-qt-lib)

### Changed

Expand Down
2 changes: 2 additions & 0 deletions crates/cxx-qt-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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=["derive"], optional = true }

[build-dependencies]
cxx-qt-build.workspace = true
Expand All @@ -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"]
23 changes: 23 additions & 0 deletions crates/cxx-qt-lib/src/core/qstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down Expand Up @@ -293,6 +298,15 @@ impl From<&String> for QString {
}
}

impl From<String> 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
///
Expand All @@ -302,6 +316,15 @@ impl From<&QString> for String {
}
}

impl From<QString> 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 {
Expand Down
2 changes: 1 addition & 1 deletion examples/qml_features/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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=["serde"] }
serde.workspace = true
serde_json.workspace = true

Expand Down
38 changes: 6 additions & 32 deletions examples/qml_features/rust/src/serialisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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<DataSerde> 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()));
Expand All @@ -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::<DataSerde>(&string.to_string()) {
pub fn from_json_str(mut self: Pin<&mut Self>, qstring: &QString) {
match serde_json::from_str::<SerialisationRust>(&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()));
Expand Down

0 comments on commit fdb5100

Please sign in to comment.