Skip to content

Conversation

@chaokunyang
Copy link
Collaborator

@chaokunyang chaokunyang commented Oct 1, 2025

Why?

Rust dyn trait object serialization support will be very useful for object-oritiened programing for complex systems

What does this PR do?

This PR supports serializing trait objects with polymorphism, enabling dynamic dispatch and type flexibility.

Box-Based Trait Objects

Serialize trait objects using Box<dyn Trait>:

use fory_core::{Fory, register_trait_type};
use fory_derive::Fory;
use fory_core::types::Mode;
use fory_core::serializer::Serializer;

trait Animal : Serializer {
    fn speak(&self) -> String;
    fn name(&self) -> &str;
}

#[derive(Fory)]
struct Dog { name: String, breed: String }

impl Animal for Dog {
    fn speak(&self) -> String { "Woof!".to_string() }
    fn name(&self) -> &str { &self.name }
}

#[derive(Fory)]
struct Cat { name: String, color: String }

impl Animal for Cat {
    fn speak(&self) -> String { "Meow!".to_string() }
    fn name(&self) -> &str { &self.name }
}

register_trait_type!(Animal, Dog, Cat);

#[derive(Fory)]
struct Zoo {
    star_animal: Box<dyn Animal>,
}

let mut fory = Fory::default().mode(Mode::Compatible);
fory.register::<Dog>(100);
fory.register::<Cat>(101);
fory.register::<Zoo>(102);

let zoo = Zoo {
    star_animal: Box::new(Dog {
        name: "Buddy".to_string(),
        breed: "Labrador".to_string(),
    }),
};

let serialized = fory.serialize(&zoo);
let deserialized: Zoo = fory.deserialize(&serialized)?;

assert_eq!(deserialized.star_animal.name(), "Buddy");
assert_eq!(deserialized.star_animal.speak(), "Woof!");

Rc/Arc-Based Trait Objects

For fields with Rc<dyn Trait> or Arc<dyn Trait>, use them directly in struct definitions:

use std::sync::Arc;
use std::rc::Rc;
use std::collections::HashMap;

#[derive(Fory)]
struct AnimalShelter {
    animals_rc: Vec<Rc<dyn Animal>>,
    animals_arc: Vec<Arc<dyn Animal>>,
    registry: HashMap<String, Arc<dyn Animal>>,
}

let mut fory = Fory::default().mode(Mode::Compatible);
fory.register::<Dog>(100);
fory.register::<Cat>(101);
fory.register::<AnimalShelter>(102);

let shelter = AnimalShelter {
    animals_rc: vec![
        Rc::new(Dog { name: "Rex".to_string(), breed: "Golden".to_string() }),
        Rc::new(Cat { name: "Mittens".to_string(), color: "Gray".to_string() }),
    ],
    animals_arc: vec![
        Arc::new(Dog { name: "Buddy".to_string(), breed: "Labrador".to_string() }),
    ],
    registry: HashMap::from([
        ("pet1".to_string(), Arc::new(Dog {
            name: "Max".to_string(),
            breed: "Shepherd".to_string()
        }) as Arc<dyn Animal>),
    ]),
};

let serialized = fory.serialize(&shelter);
let deserialized: AnimalShelter = fory.deserialize(&serialized)?;

assert_eq!(deserialized.animals_rc[0].name(), "Rex");
assert_eq!(deserialized.animals_arc[0].speak(), "Woof!");

Wrapper Types for Standalone Usage

Due to Rust's orphan rule, Rc<dyn Trait> and Arc<dyn Trait> cannot implement Serializer directly. For standalone serialization (not inside struct fields), use the auto-generated wrapper types:

// register_trait_type! generates: AnimalRc and AnimalArc

// Wrap Rc/Arc trait objects
let dog_rc: Rc<dyn Animal> = Rc::new(Dog {
    name: "Rex".to_string(),
    breed: "Golden".to_string()
});
let wrapper = AnimalRc::from(dog_rc);

// Serialize the wrapper
let serialized = fory.serialize(&wrapper);
let deserialized: AnimalRc = fory.deserialize(&serialized)?;

// Unwrap back to Rc<dyn Animal>
let unwrapped: Rc<dyn Animal> = deserialized.unwrap();
assert_eq!(unwrapped.name(), "Rex");

Related issues

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
  • Does this PR introduce any binary protocol compatibility change?

Benchmark

@chaokunyang chaokunyang requested a review from pandalee99 October 1, 2025 00:24
@chaokunyang chaokunyang marked this pull request as draft October 1, 2025 00:24
@chaokunyang chaokunyang marked this pull request as ready for review October 5, 2025 07:34
@chaokunyang chaokunyang requested a review from urlyy October 5, 2025 07:34
@chaokunyang chaokunyang merged commit 1221b51 into apache:main Oct 5, 2025
54 checks passed
@chaokunyang
Copy link
Collaborator Author

dyn Any is supported in #2704

chaokunyang added a commit that referenced this pull request Oct 6, 2025
…#2704)

## Why?

<!-- Describe the purpose of this PR. -->

## What does this PR do?

suport dyn any trait object serialization for box/arc/rc:
- introduce `ForyDefault` trait to work around orphan rule, so we can
impl `default` for `Rc<dny Any>`
- rename `Fory` derive to `ForyObject` derive
- add serializer impl for `Box/Rc/Arc<any>`
- support shared reference for `Rc/Arc<any>`
- introduce `write_any_typeinfo/read_typeinfo` for dynamic type-meta
read/write

## Related issues

#2691
#1797 
#1795

## 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.
-->
chaokunyang added a commit that referenced this pull request Oct 6, 2025
## Why?

<!-- Describe the purpose of this PR. -->

## What does this PR do?

This PR supports shared ref for arc/rc<dny T> by forward
serialization/deserialization to `arc/rc<dny T>` using `upcast/downcast`

## Related issues

Closes #2705 
#2691 
#2704 

## 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.
-->
chaokunyang added a commit that referenced this pull request Oct 6, 2025
…odule conflict (#2708)

## Why?

<!-- Describe the purpose of this PR. -->

## What does this PR do?

 fix multiple trait objects in same module `from_any_internal` conflict

## Related issues

#2691 

## 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.
-->
chaokunyang added a commit that referenced this pull request Oct 6, 2025
)

<!--
**Thanks for contributing to Apache Fory™.**

**If this is your first time opening a PR on fory, you can refer to
[CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).**

Contribution Checklist

- The **Apache Fory™** community has requirements on the naming of pr
titles. You can also find instructions in
[CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).

- Apache Fory™ has a strong focus on performance. If the PR you submit
will have an impact on performance, please benchmark it first and
provide the benchmark result here.
-->

## Why?

<!-- Describe the purpose of this PR. -->

## What does this PR do?

unify rc/arc wrapper macro arms into one function to reduce duplicate
code

## Related issues

#2691 
#2709

## 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.
-->
urlyy pushed a commit to urlyy/fory that referenced this pull request Oct 7, 2025
…ache#2711)

<!--
**Thanks for contributing to Apache Fory™.**

**If this is your first time opening a PR on fory, you can refer to
[CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).**

Contribution Checklist

- The **Apache Fory™** community has requirements on the naming of pr
titles. You can also find instructions in
[CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).

- Apache Fory™ has a strong focus on performance. If the PR you submit
will have an impact on performance, please benchmark it first and
provide the benchmark result here.
-->

## Why?

<!-- Describe the purpose of this PR. -->

## What does this PR do?

unify rc/arc wrapper macro arms into one function to reduce duplicate
code

## Related issues

apache#2691 
apache#2709

## 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.
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants