diff --git a/CHANGELOG.md b/CHANGELOG.md index 214fd327d..b618670f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ensure that generated Rust code works when `#![deny(missing_docs)]` is enabled - Ability to connect and disconnect from signals in Rust triggering a function pointer - `unsafe impl !cxx_qt::Locking for qobject::T` to disable internal locking +- `Deref` is now implemented for `qobject::T` to reach the `T` Rust struct ### Changed diff --git a/crates/cxx-qt-gen/src/generator/rust/property/getter.rs b/crates/cxx-qt-gen/src/generator/rust/property/getter.rs index 8217e4d97..cd32476ad 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/getter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/getter.rs @@ -43,7 +43,7 @@ pub fn generate( #[doc = "Getter for the Q_PROPERTY "] #[doc = #ident_str] pub fn #getter_rust(&self) -> &#ty { - &self.rust().#ident + &self.#ident } } }, diff --git a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs index f325aabad..b527d330c 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs @@ -117,7 +117,7 @@ mod tests { #[doc = "Getter for the Q_PROPERTY "] #[doc = "trivial_property"] pub fn trivial_property(&self) -> &i32 { - &self.rust().trivial_property + &self.trivial_property } } }, @@ -151,7 +151,7 @@ mod tests { #[doc = "Setter for the Q_PROPERTY "] #[doc = "trivial_property"] pub fn set_trivial_property(mut self: Pin<&mut Self>, value: i32) { - if self.rust().trivial_property == value { + if self.trivial_property == value { return; } self.as_mut().rust_mut().trivial_property = value; @@ -191,7 +191,7 @@ mod tests { #[doc = "Getter for the Q_PROPERTY "] #[doc = "opaque_property"] pub fn opaque_property(&self) -> &UniquePtr { - &self.rust().opaque_property + &self.opaque_property } } }, @@ -225,7 +225,7 @@ mod tests { #[doc = "Setter for the Q_PROPERTY "] #[doc = "opaque_property"] pub fn set_opaque_property(mut self: Pin<&mut Self>, value: UniquePtr) { - if self.rust().opaque_property == value { + if self.opaque_property == value { return; } self.as_mut().rust_mut().opaque_property = value; @@ -265,7 +265,7 @@ mod tests { #[doc = "Getter for the Q_PROPERTY "] #[doc = "unsafe_property"] pub fn unsafe_property(&self) -> &*mut T { - &self.rust().unsafe_property + &self.unsafe_property } } }, @@ -299,7 +299,7 @@ mod tests { #[doc = "Setter for the Q_PROPERTY "] #[doc = "unsafe_property"] pub fn set_unsafe_property(mut self: Pin<&mut Self>, value: *mut T) { - if self.rust().unsafe_property == value { + if self.unsafe_property == value { return; } self.as_mut().rust_mut().unsafe_property = value; diff --git a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs index 15e956b9d..8d1f13dba 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs @@ -51,7 +51,7 @@ pub fn generate( #[doc = "Setter for the Q_PROPERTY "] #[doc = #ident_str] pub fn #setter_rust(mut self: Pin<&mut Self>, value: #ty) { - if self.rust().#ident == value { + if self.#ident == value { // don't want to set the value again and reemit the signal, // as this can cause binding loops return; diff --git a/crates/cxx-qt-gen/src/writer/rust/mod.rs b/crates/cxx-qt-gen/src/writer/rust/mod.rs index 8e6b8f3b5..cf30e211c 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -35,19 +35,30 @@ fn cxx_qt_common_blocks(qobject: &GeneratedRustQObject) -> Vec { let cpp_struct_ident = &qobject.cpp_struct_ident; let rust_struct_ident = &qobject.rust_struct_ident; - vec![quote! { - impl cxx_qt::CxxQtType for #cpp_struct_ident { - type Rust = #rust_struct_ident; + vec![ + quote! { + impl core::ops::Deref for #cpp_struct_ident { + type Target = #rust_struct_ident; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } } + }, + quote! { + impl cxx_qt::CxxQtType for #cpp_struct_ident { + type Rust = #rust_struct_ident; + + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() + } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() + fn rust_mut(self: core::pin::Pin<&mut Self>) -> Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() + } } - } - }] + }, + ] } /// For a given GeneratedRustBlocks write this into a Rust TokenStream @@ -365,6 +376,14 @@ mod tests { } } + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } + impl cxx_qt::CxxQtType for MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { @@ -466,6 +485,14 @@ mod tests { } } + impl core::ops::Deref for FirstObject { + type Target = FirstObjectRust; + + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } + impl cxx_qt::CxxQtType for FirstObject { type Rust = FirstObjectRust; fn rust(&self) -> &Self::Rust { @@ -485,6 +512,14 @@ mod tests { } } + impl core::ops::Deref for SecondObject { + type Target = SecondObjectRust; + + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } + impl cxx_qt::CxxQtType for SecondObject { type Rust = SecondObjectRust; fn rust(&self) -> &Self::Rust { diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index 9878cca38..0b5c6d3a7 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -109,6 +109,12 @@ pub mod cxx_qt_inheritance { pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } impl cxx_qt::CxxQtType for MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index 96f694122..e71f13bbb 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -319,6 +319,12 @@ pub mod cxx_qt_ffi { initialize_arguments, ) } + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } impl cxx_qt::CxxQtType for MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { diff --git a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs index 7230c694c..07f2a5db6 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -231,7 +231,7 @@ pub mod cxx_qt_ffi { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] pub fn property_name(&self) -> &i32 { - &self.rust().property_name + &self.property_name } } impl MyObjectRust { @@ -244,7 +244,7 @@ pub mod cxx_qt_ffi { #[doc = "Setter for the Q_PROPERTY "] #[doc = "property_name"] pub fn set_property_name(mut self: Pin<&mut Self>, value: i32) { - if self.rust().property_name == value { + if self.property_name == value { return; } self.as_mut().rust_mut().property_name = value; @@ -290,6 +290,12 @@ pub mod cxx_qt_ffi { pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } impl cxx_qt::CxxQtType for MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { @@ -310,7 +316,7 @@ pub mod cxx_qt_ffi { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] pub fn property_name(&self) -> &i32 { - &self.rust().property_name + &self.property_name } } impl SecondObjectRust { @@ -323,7 +329,7 @@ pub mod cxx_qt_ffi { #[doc = "Setter for the Q_PROPERTY "] #[doc = "property_name"] pub fn set_property_name(mut self: Pin<&mut Self>, value: i32) { - if self.rust().property_name == value { + if self.property_name == value { return; } self.as_mut().rust_mut().property_name = value; @@ -368,6 +374,12 @@ pub mod cxx_qt_ffi { pub fn create_rs_second_object_rust() -> std::boxed::Box { core::default::Default::default() } + impl core::ops::Deref for SecondObject { + type Target = SecondObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } impl cxx_qt::CxxQtType for SecondObject { type Rust = SecondObjectRust; fn rust(&self) -> &Self::Rust { diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 4059d9305..5e59225bb 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -118,7 +118,7 @@ pub mod cxx_qt_ffi { #[doc = "Getter for the Q_PROPERTY "] #[doc = "primitive"] pub fn primitive(&self) -> &i32 { - &self.rust().primitive + &self.primitive } } impl MyObjectRust { @@ -131,7 +131,7 @@ pub mod cxx_qt_ffi { #[doc = "Setter for the Q_PROPERTY "] #[doc = "primitive"] pub fn set_primitive(mut self: Pin<&mut Self>, value: i32) { - if self.rust().primitive == value { + if self.primitive == value { return; } self.as_mut().rust_mut().primitive = value; @@ -148,7 +148,7 @@ pub mod cxx_qt_ffi { #[doc = "Getter for the Q_PROPERTY "] #[doc = "trivial"] pub fn trivial(&self) -> &QPoint { - &self.rust().trivial + &self.trivial } } impl MyObjectRust { @@ -161,7 +161,7 @@ pub mod cxx_qt_ffi { #[doc = "Setter for the Q_PROPERTY "] #[doc = "trivial"] pub fn set_trivial(mut self: Pin<&mut Self>, value: QPoint) { - if self.rust().trivial == value { + if self.trivial == value { return; } self.as_mut().rust_mut().trivial = value; @@ -201,6 +201,12 @@ pub mod cxx_qt_ffi { pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } impl cxx_qt::CxxQtType for MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 6a8007185..9f4aacce8 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -199,6 +199,12 @@ pub mod cxx_qt_ffi { pub fn create_rs_my_object_rust() -> std::boxed::Box { core::default::Default::default() } + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } impl cxx_qt::CxxQtType for MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { diff --git a/examples/demo_threading/rust/src/lib.rs b/examples/demo_threading/rust/src/lib.rs index 1ec7d1e58..521f8da3a 100644 --- a/examples/demo_threading/rust/src/lib.rs +++ b/examples/demo_threading/rust/src/lib.rs @@ -131,9 +131,8 @@ impl cxx_qt::Constructor<()> for qobject::EnergyUsage { EnergyUsageRust::default() } - /// A Q_INVOKABLE which starts the TCP server fn initialize(mut self: core::pin::Pin<&mut Self>, _arguments: Self::InitializeArguments) { - if self.rust().join_handles.is_some() { + if self.join_handles.is_some() { println!("Already running a server!"); return; } diff --git a/examples/qml_features/rust/src/custom_base_class.rs b/examples/qml_features/rust/src/custom_base_class.rs index 201098733..730456866 100644 --- a/examples/qml_features/rust/src/custom_base_class.rs +++ b/examples/qml_features/rust/src/custom_base_class.rs @@ -209,11 +209,11 @@ impl qobject::CustomBaseClass { } fn add_cpp_context(mut self: Pin<&mut Self>) { - let count = self.as_ref().rust().vector.len(); + let count = self.vector.len(); unsafe { self.as_mut() .begin_insert_rows(&QModelIndex::default(), count as i32, count as i32); - let id = self.as_ref().rust().id; + let id = self.id; self.as_mut().rust_mut().id = id + 1; self.as_mut() .rust_mut() @@ -255,7 +255,7 @@ impl qobject::CustomBaseClass { /// Remove the row with the given index pub fn remove(mut self: Pin<&mut Self>, index: i32) { - if index < 0 || (index as usize) >= self.as_ref().rust().vector.len() { + if index < 0 || (index as usize) >= self.vector.len() { return; } @@ -278,7 +278,7 @@ impl qobject::CustomBaseClass { pub const VALUE_ROLE: i32 = 1; fn data(&self, index: &QModelIndex, role: i32) -> QVariant { - if let Some((id, value)) = self.rust().vector.get(index.row() as usize) { + if let Some((id, value)) = self.vector.get(index.row() as usize) { return match role { Self::ID_ROLE => QVariant::from(id), Self::VALUE_ROLE => QVariant::from(value), @@ -312,7 +312,7 @@ impl qobject::CustomBaseClass { /// Return the row count for the QAbstractListModel pub fn row_count(&self, _parent: &QModelIndex) -> i32 { - self.rust().vector.len() as i32 + self.vector.len() as i32 } } // ANCHOR_END: book_macro_code diff --git a/examples/qml_features/rust/src/invokables.rs b/examples/qml_features/rust/src/invokables.rs index bd5ebc125..74485e8c3 100644 --- a/examples/qml_features/rust/src/invokables.rs +++ b/examples/qml_features/rust/src/invokables.rs @@ -62,7 +62,7 @@ impl Default for RustInvokablesRust { impl qobject::RustInvokables { /// Immutable invokable method that returns the QColor fn load_color(&self) -> QColor { - self.rust().as_qcolor() + self.as_qcolor() } /// Mutable invokable method that stores a color diff --git a/examples/qml_features/rust/src/signals.rs b/examples/qml_features/rust/src/signals.rs index 236d80cba..c04e6ab1d 100644 --- a/examples/qml_features/rust/src/signals.rs +++ b/examples/qml_features/rust/src/signals.rs @@ -113,7 +113,7 @@ impl cxx_qt::Constructor<()> for qobject::RustSignals { // Determine if logging is enabled if *qobject.as_ref().logging_enabled() { // If no connections have been made, then create them - if qobject.as_ref().rust().connections.is_none() { + if qobject.as_ref().connections.is_none() { // ANCHOR: book_signals_connect let connections = [ qobject.as_mut().on_connected(|_, url| { diff --git a/tests/basic_cxx_qt/rust/src/lib.rs b/tests/basic_cxx_qt/rust/src/lib.rs index 66e6feb6d..3a9f890b5 100644 --- a/tests/basic_cxx_qt/rust/src/lib.rs +++ b/tests/basic_cxx_qt/rust/src/lib.rs @@ -122,6 +122,6 @@ impl qobject::MyObject { } fn fetch_update_call_count(&self) -> i32 { - self.rust().update_call_count + self.update_call_count } } diff --git a/tests/basic_cxx_qt/rust/src/locking.rs b/tests/basic_cxx_qt/rust/src/locking.rs index 04b9bf28d..2f69e6450 100644 --- a/tests/basic_cxx_qt/rust/src/locking.rs +++ b/tests/basic_cxx_qt/rust/src/locking.rs @@ -48,13 +48,13 @@ pub struct RustLockingEnabledRust { impl qobject::RustLockingEnabled { fn get_counter(&self) -> u32 { - self.rust().counter.load(Ordering::Acquire) + self.counter.load(Ordering::Acquire) } fn increment(self: Pin<&mut Self>) { - let counter = self.as_ref().get_counter(); + let counter = self.get_counter(); thread::sleep(Duration::from_millis(100)); - self.rust().counter.store(counter + 1, Ordering::Release); + self.counter.store(counter + 1, Ordering::Release); } } @@ -65,12 +65,12 @@ pub struct RustLockingDisabledRust { impl qobject::RustLockingDisabled { fn get_counter(&self) -> u32 { - self.rust().counter.load(Ordering::Acquire) + self.counter.load(Ordering::Acquire) } fn increment(self: Pin<&mut Self>) { - let counter = self.as_ref().get_counter(); + let counter = self.get_counter(); thread::sleep(Duration::from_millis(100)); - self.rust().counter.store(counter + 1, Ordering::Release); + self.counter.store(counter + 1, Ordering::Release); } }