Skip to content

Commit fdb5100

Browse files
feat: lib: Serde support for QString (#944)
See also: #943 Co-authored-by: Montel Laurent <[email protected]>
1 parent add14e0 commit fdb5100

File tree

5 files changed

+33
-33
lines changed

5 files changed

+33
-33
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- `c_void` in CXX-Qt-lib for easy access to `void *`
2525
- `CxxQtThread` is now marked as `Sync` so that it can be used by reference
2626
- Add cxx-qt-lib-extras crate which contains: `QCommandLineOption`, `QCommandLineParser`, `QElapsedTimer`, `QApplication`
27+
- Serde support for `QString` (requires "serde" feature on cxx-qt-lib)
2728

2829
### Changed
2930

crates/cxx-qt-lib/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ http = { version = "1.0", optional = true }
2222
rgb = { version = "0.8", optional = true }
2323
time = { version = "0.3.20", optional = true }
2424
url = { version = "2.3", optional = true }
25+
serde = { version = "1", features=["derive"], optional = true }
2526

2627
[build-dependencies]
2728
cxx-qt-build.workspace = true
@@ -37,4 +38,5 @@ qt_gui = ["cxx-qt-lib-headers/qt_gui"]
3738
qt_qml = ["cxx-qt-lib-headers/qt_qml"]
3839
time = ["dep:time"]
3940
url = ["dep:url"]
41+
serde = ["dep:serde"]
4042
link_qt_object_files = ["cxx-qt-build/link_qt_object_files"]

crates/cxx-qt-lib/src/core/qstring.rs

+23
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,15 @@ mod ffi {
191191
}
192192
}
193193

194+
#[cfg(feature = "serde")]
195+
use serde::{Deserialize, Serialize};
196+
194197
/// The QString class provides a Unicode character string.
195198
///
196199
/// Note that QString is a UTF-16 whereas Rust strings are a UTF-8
197200
#[repr(C)]
201+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
202+
#[cfg_attr(feature = "serde", serde(from = "String", into = "String"))]
198203
pub struct QString {
199204
/// The layout has changed between Qt 5 and Qt 6
200205
///
@@ -293,6 +298,15 @@ impl From<&String> for QString {
293298
}
294299
}
295300

301+
impl From<String> for QString {
302+
/// Constructs a QString from a Rust string
303+
///
304+
/// Note that this converts from UTF-8 to UTF-16
305+
fn from(str: String) -> Self {
306+
ffi::qstring_init_from_rust_string(&str)
307+
}
308+
}
309+
296310
impl From<&QString> for String {
297311
/// Convert the QString to a Rust string
298312
///
@@ -302,6 +316,15 @@ impl From<&QString> for String {
302316
}
303317
}
304318

319+
impl From<QString> for String {
320+
/// Convert the QString to a Rust string
321+
///
322+
/// Note that this converts from UTF-16 to UTF-8
323+
fn from(qstring: QString) -> Self {
324+
ffi::qstring_to_rust_string(&qstring)
325+
}
326+
}
327+
305328
impl QString {
306329
/// Returns a copy of this string with the lowest numbered place marker replaced by string a, i.e., %1, %2, ..., %99.
307330
pub fn arg(&self, a: &QString) -> Self {

examples/qml_features/rust/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ crate-type = ["staticlib"]
1616
[dependencies]
1717
cxx.workspace = true
1818
cxx-qt.workspace = true
19-
cxx-qt-lib.workspace = true
19+
cxx-qt-lib = { workspace = true, features=["serde"] }
2020
serde.workspace = true
2121
serde_json.workspace = true
2222

examples/qml_features/rust/src/serialisation.rs

+6-32
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,6 @@
1010

1111
use serde::{Deserialize, Serialize};
1212

13-
/// A struct representating our serialised form
14-
#[derive(Deserialize, Serialize)]
15-
pub struct DataSerde {
16-
number: i32,
17-
string: String,
18-
}
19-
20-
impl From<&SerialisationRust> for DataSerde {
21-
fn from(value: &SerialisationRust) -> DataSerde {
22-
DataSerde {
23-
number: value.number,
24-
string: value.string.to_string(),
25-
}
26-
}
27-
}
28-
2913
/// A CXX-Qt bridge which shows how use serde for (de)serialization of the data in a QObjects' QPROPERTY's
3014
#[cxx_qt::bridge(cxx_file_stem = "serialisation")]
3115
pub mod qobject {
@@ -63,6 +47,7 @@ use cxx_qt::CxxQtType;
6347
use cxx_qt_lib::QString;
6448

6549
/// A QObject which can be serialised
50+
#[derive(Serialize, Deserialize)]
6651
pub struct SerialisationRust {
6752
/// The number Q_PROPERTY
6853
pub number: i32,
@@ -73,25 +58,14 @@ pub struct SerialisationRust {
7358
impl Default for SerialisationRust {
7459
fn default() -> Self {
7560
let string = r#"{"number": 4, "string": "Hello World!"}"#;
76-
let data_serde: DataSerde = serde_json::from_str(string).unwrap();
77-
data_serde.into()
78-
}
79-
}
80-
81-
impl From<DataSerde> for SerialisationRust {
82-
fn from(value: DataSerde) -> Self {
83-
Self {
84-
number: value.number,
85-
string: QString::from(&value.string),
86-
}
61+
serde_json::from_str(string).unwrap()
8762
}
8863
}
8964

9065
impl qobject::Serialisation {
9166
/// Retrieve the JSON form of this QObject
9267
pub fn as_json_str(self: Pin<&mut Self>) -> QString {
93-
let data_serde = DataSerde::from(self.rust());
94-
match serde_json::to_string(&data_serde) {
68+
match serde_json::to_string(&self.rust()) {
9569
Ok(data_string) => QString::from(&data_string),
9670
Err(err) => {
9771
self.error(QString::from(&err.to_string()));
@@ -102,11 +76,11 @@ impl qobject::Serialisation {
10276

10377
/// From a given JSON string try to load values for the Q_PROPERTYs
10478
// ANCHOR: book_grab_values
105-
pub fn from_json_str(mut self: Pin<&mut Self>, string: &QString) {
106-
match serde_json::from_str::<DataSerde>(&string.to_string()) {
79+
pub fn from_json_str(mut self: Pin<&mut Self>, qstring: &QString) {
80+
match serde_json::from_str::<SerialisationRust>(&qstring.to_string()) {
10781
Ok(data_serde) => {
10882
self.as_mut().set_number(data_serde.number);
109-
self.as_mut().set_string(QString::from(&data_serde.string));
83+
self.as_mut().set_string(data_serde.string);
11084
}
11185
Err(err) => {
11286
self.error(QString::from(&err.to_string()));

0 commit comments

Comments
 (0)