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