This is an automated email from the ASF dual-hosted git repository.
pandalee pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 0121f0fc4 feat(rust): add deref to arc/rc wrapper (#2709)
0121f0fc4 is described below
commit 0121f0fc418e90b8eafa4e56f155869f1e5933d6
Author: Shawn Yang <[email protected]>
AuthorDate: Tue Oct 7 00:11:21 2025 +0800
feat(rust): add deref to arc/rc wrapper (#2709)
## Why?
Deref/DerefMut can make a new type behave like a pointer
## What does this PR do?
add deref to arc/rc wrapper to let wrapper behave like a pointer
## Related issues
<!--
Is there any related issue? If this PR closes them you say say
fix/closes:
- #xxxx0
- #xxxx1
- Fixes #xxxx2
-->
## Does this PR introduce any user-facing change?
<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fory/issues/new/choose) describing the
need to do so and update the document if necessary.
Delete section if not applicable.
-->
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.
Delete section if not applicable.
-->
---
rust/fory-core/src/serializer/trait_object.rs | 50 +++++++++++++++++++++------
rust/tests/tests/test_rc_arc_trait_object.rs | 49 ++++++++++++++++++++++++++
2 files changed, 89 insertions(+), 10 deletions(-)
diff --git a/rust/fory-core/src/serializer/trait_object.rs
b/rust/fory-core/src/serializer/trait_object.rs
index d1d23e835..d4d191d55 100644
--- a/rust/fory-core/src/serializer/trait_object.rs
+++ b/rust/fory-core/src/serializer/trait_object.rs
@@ -284,26 +284,41 @@ macro_rules! generate_smart_pointer_wrapper {
(Rc, $trait_name:ident, $($impl_type:ty),+ $(,)?) => {
$crate::paste::paste! {
#[derive(Clone)]
- pub struct [<$trait_name Rc>](std::rc::Rc<dyn $trait_name>);
+ pub(crate) struct [<$trait_name Rc>](std::rc::Rc<dyn $trait_name>);
impl [<$trait_name Rc>] {
- pub fn new(inner: std::rc::Rc<dyn $trait_name>) -> Self {
+ pub(crate) fn new(inner: std::rc::Rc<dyn $trait_name>) -> Self
{
Self(inner)
}
- pub fn into_inner(self) -> std::rc::Rc<dyn $trait_name> {
+ pub(crate) fn into_inner(self) -> std::rc::Rc<dyn $trait_name>
{
self.0
}
- pub fn unwrap(self) -> std::rc::Rc<dyn $trait_name> {
+ pub(crate) fn unwrap(self) -> std::rc::Rc<dyn $trait_name> {
self.0
}
- pub fn as_ref(&self) -> &dyn $trait_name {
+ pub(crate) fn as_ref(&self) -> &dyn $trait_name {
&*self.0
}
}
+ impl std::ops::Deref for [<$trait_name Rc>] {
+ type Target = dyn $trait_name;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.0
+ }
+ }
+
+ impl std::ops::DerefMut for [<$trait_name Rc>] {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ std::rc::Rc::get_mut(&mut self.0)
+ .expect("Cannot get mutable reference to Rc with
multiple strong references")
+ }
+ }
+
impl From<std::rc::Rc<dyn $trait_name>> for [<$trait_name Rc>] {
fn from(ptr: std::rc::Rc<dyn $trait_name>) -> Self {
Self::new(ptr)
@@ -356,26 +371,41 @@ macro_rules! generate_smart_pointer_wrapper {
(Arc, $trait_name:ident, $($impl_type:ty),+ $(,)?) => {
$crate::paste::paste! {
#[derive(Clone)]
- pub struct [<$trait_name Arc>](std::sync::Arc<dyn $trait_name>);
+ pub(crate) struct [<$trait_name Arc>](std::sync::Arc<dyn
$trait_name>);
impl [<$trait_name Arc>] {
- pub fn new(inner: std::sync::Arc<dyn $trait_name>) -> Self {
+ pub(crate) fn new(inner: std::sync::Arc<dyn $trait_name>) ->
Self {
Self(inner)
}
- pub fn into_inner(self) -> std::sync::Arc<dyn $trait_name> {
+ pub(crate) fn into_inner(self) -> std::sync::Arc<dyn
$trait_name> {
self.0
}
- pub fn unwrap(self) -> std::sync::Arc<dyn $trait_name> {
+ pub(crate) fn unwrap(self) -> std::sync::Arc<dyn $trait_name> {
self.0
}
- pub fn as_ref(&self) -> &dyn $trait_name {
+ pub(crate) fn as_ref(&self) -> &dyn $trait_name {
&*self.0
}
}
+ impl std::ops::Deref for [<$trait_name Arc>] {
+ type Target = dyn $trait_name;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.0
+ }
+ }
+
+ impl std::ops::DerefMut for [<$trait_name Arc>] {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ std::sync::Arc::get_mut(&mut self.0)
+ .expect("Cannot get mutable reference to Arc with
multiple strong references")
+ }
+ }
+
impl From<std::sync::Arc<dyn $trait_name>> for [<$trait_name Arc>]
{
fn from(ptr: std::sync::Arc<dyn $trait_name>) -> Self {
Self::new(ptr)
diff --git a/rust/tests/tests/test_rc_arc_trait_object.rs
b/rust/tests/tests/test_rc_arc_trait_object.rs
index 42dc90744..92bfe0a66 100644
--- a/rust/tests/tests/test_rc_arc_trait_object.rs
+++ b/rust/tests/tests/test_rc_arc_trait_object.rs
@@ -32,6 +32,7 @@ fn fory_compatible() -> Fory {
trait Animal: Serializer + Send + Sync {
fn speak(&self) -> String;
fn name(&self) -> &str;
+ fn set_name(&mut self, name: String);
}
#[derive(ForyObject, Debug, PartialEq)]
@@ -48,6 +49,10 @@ impl Animal for Dog {
fn name(&self) -> &str {
&self.name
}
+
+ fn set_name(&mut self, name: String) {
+ self.name = name;
+ }
}
#[derive(ForyObject, Debug, PartialEq)]
@@ -64,6 +69,10 @@ impl Animal for Cat {
fn name(&self) -> &str {
&self.name
}
+
+ fn set_name(&mut self, name: String) {
+ self.name = name;
+ }
}
register_trait_type!(Animal, Dog, Cat);
@@ -465,3 +474,43 @@ fn test_arc_shared_ref_tracking() {
assert!(Arc::ptr_eq(&arc0, &arc1));
assert!(Arc::ptr_eq(&arc1, &arc2));
}
+
+#[test]
+fn test_deref_wrapper() {
+ let dog_rc = AnimalRc::from(Rc::new(Dog {
+ name: "Rex".to_string(),
+ breed: "Golden Retriever".to_string(),
+ }) as Rc<dyn Animal>);
+
+ assert_eq!(dog_rc.name(), "Rex");
+ assert_eq!(dog_rc.speak(), "Woof!");
+
+ let cat_arc = AnimalArc::from(Arc::new(Cat {
+ name: "Whiskers".to_string(),
+ color: "Orange".to_string(),
+ }) as Arc<dyn Animal>);
+
+ assert_eq!(cat_arc.name(), "Whiskers");
+ assert_eq!(cat_arc.speak(), "Meow!");
+}
+
+#[test]
+fn test_deref_mut_wrapper() {
+ let mut dog_rc = AnimalRc::from(Rc::new(Dog {
+ name: "Rex".to_string(),
+ breed: "Golden Retriever".to_string(),
+ }) as Rc<dyn Animal>);
+
+ assert_eq!(dog_rc.name(), "Rex");
+ dog_rc.set_name("Max".to_string());
+ assert_eq!(dog_rc.name(), "Max");
+
+ let mut cat_arc = AnimalArc::from(Arc::new(Cat {
+ name: "Whiskers".to_string(),
+ color: "Orange".to_string(),
+ }) as Arc<dyn Animal>);
+
+ assert_eq!(cat_arc.name(), "Whiskers");
+ cat_arc.set_name("Mittens".to_string());
+ assert_eq!(cat_arc.name(), "Mittens");
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]