Skip to main content

fory_core/serializer/
trait_object.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18// Re-exports for use in macros - these are needed for macro expansion in user crates
19// Even though they appear unused in this file, they are used by the macro-generated code
20
21use crate::ensure;
22use crate::error::Error;
23use crate::resolver::context::{ReadContext, WriteContext};
24use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
25use crate::serializer::{ForyDefault, Serializer};
26use crate::types::RefMode;
27use crate::RefFlag;
28use crate::TypeId;
29use std::rc::Rc;
30
31/// Helper macro for common type resolution and downcasting pattern
32#[macro_export]
33macro_rules! downcast_and_serialize {
34    ($any_ref:expr, $context:expr, $trait_name:ident, $($impl_type:ty),+) => {{
35        $(
36            if $any_ref.type_id() == std::any::TypeId::of::<$impl_type>() {
37                if let Some(concrete) = $any_ref.downcast_ref::<$impl_type>() {
38                    concrete.fory_write_data($context)?;
39                    return Ok(());
40                }
41            }
42        )*
43        return Err(fory_core::Error::type_error(format!("Failed to downcast to any registered type for trait {}", stringify!($trait_name))));
44    }};
45}
46
47/// Macro to register trait object conversions for custom traits.
48///
49/// This macro automatically generates serializers for `Box<dyn Trait>` trait objects.
50/// Due to Rust's orphan rules, only `Box<dyn Trait>` is supported for user-defined traits.
51/// For `Rc<dyn Trait>` and `Arc<dyn Trait>`, wrapper types are generated (e.g., `TraitRc`, `TraitArc`),
52/// either you use the wrapper types or use the `Rc<dyn Any>` or `Arc<dyn Any>` instead if it's not
53/// inside struct fields. For struct fields, you can use the `Rc<dyn Trait>`, `Arc<dyn Trait>` directly,
54/// fory will generate converters for `Rc<dyn Trait>` and `Arc<dyn Trait>` to convert to wrapper for
55///
56/// The macro generates:
57/// - `Serializer` implementation for `Box<dyn Trait>`
58/// - `Default` implementation for `Box<dyn Trait>` (uses first registered type)
59///
60/// **Note**: Your trait must extend the `Serializer` trait.
61/// The `as_any()` method is automatically provided by the `Serializer` trait.
62///
63/// # Example
64///
65/// ```rust,ignore
66/// use fory_core::{fory::Fory, register_trait_type, serializer::Serializer};
67/// use fory_derive::ForyObject;
68///
69/// trait Animal: Serializer {
70///     fn speak(&self) -> String;
71///     fn name(&self) -> &str;
72/// }
73///
74/// #[derive(ForyObject, Debug)]
75/// struct Dog { name: String }
76///
77/// #[derive(ForyObject, Debug)]
78/// struct Cat { name: String }
79///
80/// impl Animal for Dog {
81///     fn speak(&self) -> String { "Woof!".to_string() }
82///     fn name(&self) -> &str { &self.name }
83/// }
84///
85/// impl Animal for Cat {
86///     fn speak(&self) -> String { "Meow!".to_string() }
87///     fn name(&self) -> &str { &self.name }
88/// }
89///
90/// register_trait_type!(Animal, Dog, Cat);
91///
92/// # fn main() {
93/// let mut fory = Fory::default().compatible(true);
94/// fory.register::<Dog>(100);
95/// fory.register::<Cat>(101);
96///
97/// let dog: Box<dyn Animal> = Box::new(Dog { name: "Rex".to_string() });
98/// let bytes = fory.serialize(&dog);
99/// let decoded: Box<dyn Animal> = fory.deserialize(&bytes).unwrap();
100/// assert_eq!(decoded.name(), "Rex");
101/// # }
102/// ```
103#[macro_export]
104macro_rules! register_trait_type {
105    ($trait_name:ident, $($impl_type:ty),+ $(,)?) => {
106        // 1. Generate Box<dyn Trait> serializer (existing functionality)
107        // ForyDefault implementation using first registered type
108        impl $crate::serializer::ForyDefault for Box<dyn $trait_name> {
109            fn fory_default() -> Self {
110                Box::new(<register_trait_type!(@first_type $($impl_type),+) as $crate::serializer::ForyDefault>::fory_default())
111            }
112        }
113
114        // 2. Auto-generate Rc wrapper type and conversions
115        $crate::generate_smart_pointer_wrapper!(
116            std::rc::Rc,
117            Rc,
118            std::rc::Rc::get_mut,
119            $trait_name,
120            try_write_rc_ref,
121            get_rc_ref,
122            store_rc_ref,
123            $($impl_type),+
124        );
125
126        // 3. Auto-generate Arc wrapper type and conversions
127        $crate::generate_smart_pointer_wrapper!(
128            std::sync::Arc,
129            Arc,
130            std::sync::Arc::get_mut,
131            $trait_name,
132            try_write_arc_ref,
133            get_arc_ref,
134            store_arc_ref,
135            $($impl_type),+
136        );
137
138        // 4. Serializer implementation for Box<dyn Trait> (existing functionality)
139        impl fory_core::Serializer for Box<dyn $trait_name> {
140            #[inline(always)]
141            fn fory_write(&self, context: &mut fory_core::WriteContext, ref_mode: fory_core::RefMode, write_type_info: bool, has_generics: bool) -> Result<(), fory_core::Error> {
142                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
143                fory_core::serializer::write_box_any(any_ref, context, ref_mode, write_type_info, has_generics)
144            }
145
146            #[inline(always)]
147            fn fory_write_data(&self, context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
148                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
149                fory_core::serializer::write_box_any(any_ref, context, fory_core::RefMode::None, false, false)
150            }
151
152            #[inline(always)]
153            fn fory_write_data_generic(&self, context: &mut fory_core::WriteContext, has_generics: bool) -> Result<(), fory_core::Error> {
154                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
155                fory_core::serializer::write_box_any(any_ref, context, fory_core::RefMode::None, false, has_generics)
156            }
157
158            #[inline(always)]
159            fn fory_type_id_dyn(&self, type_resolver: &fory_core::TypeResolver) -> Result<fory_core::TypeId, fory_core::Error> {
160                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
161                let concrete_type_id = any_ref.type_id();
162                type_resolver
163                    .get_fory_type_id(concrete_type_id)
164                    .ok_or_else(|| fory_core::Error::type_error("Type not registered for trait object"))
165            }
166
167            #[inline(always)]
168            fn fory_is_polymorphic() -> bool {
169                true
170            }
171
172            fn fory_write_type_info(_context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
173                $crate::not_allowed!("fory_write_type_info should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
174            }
175
176            fn fory_read_type_info(_context: &mut fory_core::ReadContext) -> Result<(), fory_core::Error> {
177                $crate::not_allowed!("fory_read_type_info should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
178            }
179
180            fn fory_read(context: &mut fory_core::ReadContext, ref_mode: fory_core::RefMode, read_type_info: bool) -> Result<Self, fory_core::Error> {
181                let boxed_any = fory_core::serializer::read_box_any(context, ref_mode, read_type_info, None)?;
182                $(
183                    if boxed_any.is::<$impl_type>() {
184                        let concrete = boxed_any.downcast::<$impl_type>()
185                            .map_err(|_| fory_core::Error::type_error("Downcast failed"))?;
186                        let ptr = Box::new(*concrete);
187                        return Ok(Self::from(ptr));
188                    }
189                )*
190                Err(fory_core::Error::type_error(
191                    format!("Deserialized type does not implement trait {}", stringify!($trait_name))
192                ))
193            }
194
195            fn fory_read_with_type_info(
196                context: &mut fory_core::ReadContext,
197                ref_mode: fory_core::RefMode,
198                type_info: std::rc::Rc<fory_core::TypeInfo>,
199            ) -> Result<Self, fory_core::Error>
200            where
201                Self: Sized + fory_core::ForyDefault,
202            {
203                let boxed_any = fory_core::serializer::read_box_any(context, ref_mode, false, Some(type_info))?;
204                $(
205                    if boxed_any.is::<$impl_type>() {
206                        let concrete = boxed_any.downcast::<$impl_type>()
207                            .map_err(|_| fory_core::Error::type_error("Downcast failed"))?;
208                        let ptr = Box::new(*concrete);
209                        return Ok(Self::from(ptr));
210                    }
211                )*
212                Err(fory_core::Error::type_error(
213                    format!("Deserialized type does not implement trait {}", stringify!($trait_name))
214                ))
215            }
216
217            fn fory_read_data(_context: &mut fory_core::ReadContext) -> Result<Self, fory_core::Error> {
218                // This should not be called for polymorphic types like Box<dyn Trait>
219                // The fory_read method handles the polymorphic dispatch
220                $crate::not_allowed!("fory_read_data should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
221            }
222
223            fn fory_get_type_id(_type_resolver: &fory_core::TypeResolver) -> Result<fory_core::TypeId, fory_core::Error> {
224                $crate::not_allowed!("fory_get_type_id should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
225            }
226
227            #[inline(always)]
228            fn fory_static_type_id() -> fory_core::TypeId {
229                fory_core::TypeId::UNKNOWN
230            }
231
232            #[inline(always)]
233            fn fory_reserved_space() -> usize {
234                $crate::types::SIZE_OF_REF_AND_TYPE
235            }
236
237            #[inline(always)]
238            fn fory_concrete_type_id(&self) -> std::any::TypeId {
239                <dyn $trait_name as fory_core::Serializer>::as_any(&**self).type_id()
240            }
241
242            #[inline(always)]
243            fn as_any(&self) -> &dyn std::any::Any {
244                <dyn $trait_name as fory_core::Serializer>::as_any(&**self)
245            }
246        }
247    };
248
249    // Helper to get first type for Default impl
250    (@first_type $first_type:ty $(, $rest:ty)*) => {
251        $first_type
252    };
253}
254
255/// Unified macro to generate smart pointer wrapper types for traits
256/// Supports both Rc and Arc pointer types
257#[macro_export]
258macro_rules! generate_smart_pointer_wrapper {
259    ($ptr_path:path, $ptr_name:ident, $get_mut:path, $trait_name:ident, $try_write_ref:ident, $get_ref:ident, $store_ref:ident, $($impl_type:ty),+ $(,)?) => {
260        $crate::paste::paste! {
261            #[derive(Clone)]
262            pub(crate) struct [<$trait_name $ptr_name>]($ptr_path<dyn $trait_name>);
263
264            impl [<$trait_name $ptr_name>] {
265                pub(crate) fn new(inner: $ptr_path<dyn $trait_name>) -> Self {
266                    Self(inner)
267                }
268
269                pub(crate) fn into_inner(self) -> $ptr_path<dyn $trait_name> {
270                    self.0
271                }
272
273                pub(crate) fn unwrap(self) -> $ptr_path<dyn $trait_name> {
274                    self.0
275                }
276
277                pub(crate) fn as_ref(&self) -> &dyn $trait_name {
278                    &*self.0
279                }
280            }
281
282            impl std::ops::Deref for [<$trait_name $ptr_name>] {
283                type Target = dyn $trait_name;
284
285                fn deref(&self) -> &Self::Target {
286                    &*self.0
287                }
288            }
289
290            impl std::ops::DerefMut for [<$trait_name $ptr_name>] {
291                fn deref_mut(&mut self) -> &mut Self::Target {
292                    $get_mut(&mut self.0)
293                        .expect(&format!("Cannot get mutable reference to {} with multiple strong references", stringify!($ptr_name)))
294                }
295            }
296
297            impl From<$ptr_path<dyn $trait_name>> for [<$trait_name $ptr_name>] {
298                fn from(ptr: $ptr_path<dyn $trait_name>) -> Self {
299                    Self::new(ptr)
300                }
301            }
302
303            impl From<[<$trait_name $ptr_name>]> for $ptr_path<dyn $trait_name> {
304                fn from(wrapper: [<$trait_name $ptr_name>]) -> Self {
305                    wrapper.into_inner()
306                }
307            }
308
309            impl $crate::serializer::ForyDefault for [<$trait_name $ptr_name>] {
310                fn fory_default() -> Self {
311                    Self($ptr_path::new(<$crate::register_trait_type!(@first_type $($impl_type),+) as $crate::serializer::ForyDefault>::fory_default()))
312                }
313            }
314
315            impl std::fmt::Debug for [<$trait_name $ptr_name>] {
316                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
317                    let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
318                    $(
319                        if let Some(concrete) = any_obj.downcast_ref::<$impl_type>() {
320                            return write!(f, concat!(stringify!($trait_name), stringify!($ptr_name), "({:?})"), concrete);
321                        }
322                    )*
323                    write!(f, concat!(stringify!($trait_name), stringify!($ptr_name), "({:p})"), &*self.0)
324                }
325            }
326
327            $crate::impl_smart_pointer_serializer!(
328                [<$trait_name $ptr_name>],
329                $ptr_path<dyn $trait_name>,
330                $ptr_path::new,
331                $trait_name,
332                $try_write_ref,
333                $get_ref,
334                $store_ref,
335                $($impl_type),+
336            );
337        }
338    };
339}
340
341/// Macro to read smart pointer trait objects (`Rc<dyn Trait>,` `Arc<dyn Trait>`)
342/// This macro handles ref tracking and directly constructs the trait object from concrete types
343#[macro_export]
344macro_rules! read_ptr_trait_object {
345    ($context:expr, $ref_mode:expr, $read_type_info:expr, $type_info:expr, $pointer_type:ty, $trait_name:ident, $constructor_expr:expr, $get_ref:ident, $store_ref:ident, $($impl_type:ty),+) => {{
346        let ref_flag = if $ref_mode != fory_core::RefMode::None {
347            $context.ref_reader.read_ref_flag(&mut $context.reader)?
348        } else {
349            fory_core::RefFlag::NotNullValue
350        };
351        match ref_flag {
352            fory_core::RefFlag::Null => Err(fory_core::Error::invalid_ref(format!("smart pointer to dyn {} cannot be null", stringify!($trait_name)))),
353            fory_core::RefFlag::Ref => {
354                let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
355                let ptr_ref = $context.ref_reader.$get_ref::<dyn $trait_name>(ref_id)
356                    .ok_or_else(|| fory_core::Error::invalid_data(format!("dyn {} reference {} not found", stringify!($trait_name), ref_id)))?;
357                Ok(Self::from(ptr_ref))
358            }
359            fory_core::RefFlag::NotNullValue => {
360                $context.inc_depth()?;
361                let typeinfo = if $read_type_info {
362                    $context.read_any_type_info()?
363                } else {
364                    $type_info.ok_or_else(|| fory_core::Error::type_error("No type info found for read"))?
365                };
366                let fory_type_id = typeinfo.get_type_id();
367                let user_type_id = typeinfo.get_user_type_id();
368                let registered_by_name = typeinfo.is_registered_by_name();
369                let namespace = typeinfo.get_namespace();
370                let type_name = typeinfo.get_type_name();
371                let matches_type = |local_info: &fory_core::TypeInfo| -> bool {
372                    if registered_by_name {
373                        local_info.is_registered_by_name()
374                            && local_info.get_namespace().original == namespace.original
375                            && local_info.get_type_name().original == type_name.original
376                    } else if user_type_id != u32::MAX {
377                        local_info.get_user_type_id() == user_type_id
378                    } else {
379                        local_info.get_type_id() == fory_type_id
380                    }
381                };
382                $(
383                    if let Ok(local_info) = $context.get_type_resolver().get_type_info(&std::any::TypeId::of::<$impl_type>()) {
384                        if matches_type(&local_info) {
385                            let concrete_obj = <$impl_type as fory_core::Serializer>::fory_read_data($context)?;
386                            $context.dec_depth();
387                            let ptr = $constructor_expr(concrete_obj) as $pointer_type;
388                            return Ok(Self::from(ptr));
389                        }
390                    }
391                )*
392                $context.dec_depth();
393                Err(fory_core::Error::type_error(format!(
394                    "Type ID {} not registered for trait {}",
395                    fory_type_id as u32,
396                    stringify!($trait_name)
397                )))
398            }
399            fory_core::RefFlag::RefValue => {
400                $context.inc_depth()?;
401                let typeinfo = if $read_type_info {
402                    $context.read_any_type_info()?
403                } else {
404                    $type_info.ok_or_else(|| fory_core::Error::type_error("No type info found for read"))?
405                };
406                let fory_type_id = typeinfo.get_type_id();
407                let user_type_id = typeinfo.get_user_type_id();
408                let registered_by_name = typeinfo.is_registered_by_name();
409                let namespace = typeinfo.get_namespace();
410                let type_name = typeinfo.get_type_name();
411                let matches_type = |local_info: &fory_core::TypeInfo| -> bool {
412                    if registered_by_name {
413                        local_info.is_registered_by_name()
414                            && local_info.get_namespace().original == namespace.original
415                            && local_info.get_type_name().original == type_name.original
416                    } else if user_type_id != u32::MAX {
417                        local_info.get_user_type_id() == user_type_id
418                    } else {
419                        local_info.get_type_id() == fory_type_id
420                    }
421                };
422                $(
423                    if let Ok(local_info) = $context.get_type_resolver().get_type_info(&std::any::TypeId::of::<$impl_type>()) {
424                        if matches_type(&local_info) {
425                            let concrete_obj = <$impl_type as fory_core::Serializer>::fory_read_data($context)?;
426                            $context.dec_depth();
427                            let ptr = $constructor_expr(concrete_obj) as $pointer_type;
428                            let wrapper = Self::from(ptr.clone());
429                            $context.ref_reader.$store_ref(ptr);
430                            return Ok(wrapper);
431                        }
432                    }
433                )*
434                $context.dec_depth();
435                Err(fory_core::Error::type_error(format!(
436                    "Type ID {} not registered for trait {}",
437                    fory_type_id as u32,
438                    stringify!($trait_name)
439                )))
440            }
441        }
442    }};
443}
444
445/// Shared serializer implementation for smart pointer wrappers
446#[macro_export]
447macro_rules! impl_smart_pointer_serializer {
448    ($wrapper_name:ident, $pointer_type:ty, $constructor_expr:expr, $trait_name:ident, $try_write_ref:ident, $get_ref:ident, $store_ref:ident, $($impl_type:ty),+) => {
449        impl fory_core::Serializer for $wrapper_name {
450            fn fory_write(&self, context: &mut fory_core::WriteContext, ref_mode: fory_core::RefMode, write_type_info: bool, has_generics: bool) -> Result<(), fory_core::Error> {
451                if ref_mode == fory_core::RefMode::None || !context.ref_writer.$try_write_ref(&mut context.writer, &self.0) {
452                    let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
453                    let concrete_type_id = any_obj.type_id();
454                    let typeinfo = if write_type_info {
455                         context.write_any_type_info(fory_core::TypeId::UNKNOWN as u32, concrete_type_id)?
456                    } else {
457                        context.get_type_info(&concrete_type_id)?
458                    };
459                    let serializer_fn = typeinfo.get_harness().get_write_data_fn();
460                    serializer_fn(any_obj, context, has_generics)?;
461                }
462                Ok(())
463            }
464
465            fn fory_write_data(&self, context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
466                let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
467                $crate::downcast_and_serialize!(any_obj, context, $trait_name, $($impl_type),+)
468            }
469
470            fn fory_read(context: &mut fory_core::ReadContext, ref_mode: fory_core::RefMode, read_type_info: bool) -> Result<Self, fory_core::Error> {
471                $crate::read_ptr_trait_object!(
472                    context,
473                    ref_mode,
474                    read_type_info,
475                    None,
476                    $pointer_type,
477                    $trait_name,
478                    $constructor_expr,
479                    $get_ref,
480                    $store_ref,
481                    $($impl_type),+
482                )
483            }
484
485            fn fory_read_with_type_info(context: &mut fory_core::ReadContext, ref_mode: fory_core::RefMode, type_info: std::rc::Rc<fory_core::TypeInfo>) -> Result<Self, fory_core::Error> {
486                $crate::read_ptr_trait_object!(
487                    context,
488                    ref_mode,
489                    false,
490                    Some(type_info),
491                    $pointer_type,
492                    $trait_name,
493                    $constructor_expr,
494                    $get_ref,
495                    $store_ref,
496                    $($impl_type),+
497                )
498            }
499
500            fn fory_read_data(context: &mut fory_core::ReadContext) -> Result<Self, fory_core::Error> {
501                $crate::not_allowed!("fory_read_data should not be called directly on polymorphic {}<dyn {}> trait object", stringify!($ptr_path), stringify!($trait_name))
502            }
503
504            #[inline(always)]
505            fn fory_get_type_id(_type_resolver: &fory_core::TypeResolver) -> Result<fory_core::TypeId, fory_core::Error> {
506                Ok(fory_core::TypeId::STRUCT)
507            }
508
509            #[inline(always)]
510            fn fory_static_type_id() -> fory_core::TypeId {
511                fory_core::TypeId::UNKNOWN
512            }
513
514            #[inline(always)]
515            fn fory_write_type_info(_context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
516                Ok(())
517            }
518
519            #[inline(always)]
520            fn fory_read_type_info(_context: &mut fory_core::ReadContext) -> Result<(), fory_core::Error>  {
521                Ok(())
522            }
523
524            #[inline(always)]
525            fn fory_is_polymorphic() -> bool {
526                true
527            }
528
529            #[inline(always)]
530            fn fory_is_shared_ref() -> bool {
531                true
532            }
533
534            #[inline(always)]
535            fn fory_type_id_dyn(&self, type_resolver: &fory_core::TypeResolver) -> Result<fory_core::TypeId, fory_core::Error> {
536                let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
537                let concrete_type_id = any_obj.type_id();
538                type_resolver
539                    .get_fory_type_id(concrete_type_id)
540                    .ok_or_else(|| fory_core::Error::type_error("Type not registered for trait object"))
541            }
542
543            #[inline(always)]
544            fn fory_concrete_type_id(&self) -> std::any::TypeId {
545                <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0).type_id()
546            }
547
548            #[inline(always)]
549            fn as_any(&self) -> &dyn std::any::Any {
550                <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0)
551            }
552        }
553    };
554}
555
556/// Helper macros for automatic conversions in derive code
557/// These are used by fory-derive to generate transparent conversions
558///
559/// Convert field of type `Rc<dyn Trait>` to wrapper for serialization
560#[macro_export]
561macro_rules! wrap_rc {
562    ($field:expr, $trait_name:ident) => {
563        $crate::paste::paste! {
564            [<$trait_name Rc>]::from($field)
565        }
566    };
567}
568
569/// Convert wrapper back to `Rc<dyn Trait>` for deserialization
570#[macro_export]
571macro_rules! unwrap_rc {
572    ($wrapper:expr, $trait_name:ident) => {
573        std::rc::Rc::<dyn $trait_name>::from($wrapper)
574    };
575}
576
577/// Convert `Arc<dyn Trait>` to wrapper for serialization
578#[macro_export]
579macro_rules! wrap_arc {
580    ($field:expr, $trait_name:ident) => {
581        $crate::paste::paste! {
582            [<$trait_name Arc>]::from($field)
583        }
584    };
585}
586
587/// Convert `Vec<Rc<dyn Trait>>` to `Vec<wrapper>` for serialization
588#[macro_export]
589macro_rules! wrap_vec_rc {
590    ($vec:expr, $trait_name:ident) => {
591        $crate::paste::paste! {
592            $vec.into_iter().map(|item| [<$trait_name Rc>]::from(item)).collect()
593        }
594    };
595}
596
597impl Default for Box<dyn Serializer> {
598    fn default() -> Self {
599        Box::new(0)
600    }
601}
602
603impl ForyDefault for Box<dyn Serializer> {
604    fn fory_default() -> Self {
605        Box::new(0)
606    }
607}
608
609impl Serializer for Box<dyn Serializer> {
610    #[inline(always)]
611    fn fory_concrete_type_id(&self) -> std::any::TypeId {
612        (**self).fory_concrete_type_id()
613    }
614
615    fn fory_write(
616        &self,
617        context: &mut WriteContext,
618        ref_mode: RefMode,
619        write_type_info: bool,
620        has_generics: bool,
621    ) -> Result<(), Error> {
622        if ref_mode != RefMode::None {
623            context.writer.write_i8(RefFlag::NotNullValue as i8);
624        }
625        let fory_type_id_dyn = self.fory_type_id_dyn(context.get_type_resolver())?;
626        let concrete_type_id = (**self).fory_concrete_type_id();
627        if write_type_info {
628            context.write_any_type_info(fory_type_id_dyn as u32, concrete_type_id)?;
629        };
630        self.fory_write_data_generic(context, has_generics)
631    }
632
633    #[inline(always)]
634    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
635        self.fory_write_data_generic(context, false)
636    }
637
638    #[inline(always)]
639    fn fory_write_data_generic(
640        &self,
641        context: &mut WriteContext,
642        has_generics: bool,
643    ) -> Result<(), Error> {
644        (**self).fory_write_data_generic(context, has_generics)
645    }
646
647    #[inline(always)]
648    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
649        (**self).fory_type_id_dyn(type_resolver)
650    }
651
652    #[inline(always)]
653    fn as_any(&self) -> &dyn std::any::Any {
654        (**self).as_any()
655    }
656
657    #[inline(always)]
658    fn fory_is_polymorphic() -> bool {
659        true
660    }
661
662    fn fory_write_type_info(_context: &mut WriteContext) -> Result<(), Error> {
663        Err(Error::not_allowed(
664            "Box<dyn Serializer> is polymorphic - can's write type info statically",
665        ))
666    }
667
668    #[inline(always)]
669    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
670        context.read_any_type_info()?;
671        Ok(())
672    }
673
674    #[inline(always)]
675    fn fory_read(
676        context: &mut ReadContext,
677        ref_mode: RefMode,
678        read_type_info: bool,
679    ) -> Result<Self, Error> {
680        read_box_seralizer(context, ref_mode, read_type_info, None)
681    }
682
683    #[inline(always)]
684    fn fory_read_with_type_info(
685        context: &mut ReadContext,
686        ref_mode: RefMode,
687        type_info: Rc<TypeInfo>,
688    ) -> Result<Self, Error>
689    where
690        Self: Sized + ForyDefault,
691    {
692        read_box_seralizer(context, ref_mode, false, Some(type_info))
693    }
694
695    fn fory_read_data(_context: &mut ReadContext) -> Result<Self, Error> {
696        Err(Error::not_allowed(
697            "fory_read_data should not be called directly on Box<dyn Serializer>",
698        ))
699    }
700}
701
702fn read_box_seralizer(
703    context: &mut ReadContext,
704    ref_mode: RefMode,
705    read_type_info: bool,
706    type_info: Option<Rc<TypeInfo>>,
707) -> Result<Box<dyn Serializer>, Error> {
708    context.inc_depth()?;
709    let ref_flag = if ref_mode != RefMode::None {
710        context.reader.read_i8()?
711    } else {
712        RefFlag::NotNullValue as i8
713    };
714    if ref_flag != RefFlag::NotNullValue as i8 {
715        return Err(Error::invalid_data(
716            "Expected NotNullValue for Box<dyn Serializer>",
717        ));
718    }
719    let typeinfo = if let Some(type_info) = type_info {
720        type_info
721    } else {
722        ensure!(
723            read_type_info,
724            Error::invalid_data("Type info must be read for Box<dyn Serializer>")
725        );
726        context.read_any_type_info()?
727    };
728    let harness = typeinfo.get_harness();
729    let boxed_any = harness.get_read_data_fn()(context)?;
730    let trait_object = harness.get_to_serializer()(boxed_any)?;
731    context.dec_depth();
732    Ok(trait_object)
733}