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            fn fory_write(&self, context: &mut fory_core::WriteContext, write_ref_info: bool, write_type_info: bool, has_generics: bool) -> Result<(), fory_core::Error> {
163                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
164                fory_core::serializer::write_box_any(any_ref, context, write_ref_info, write_type_info, has_generics)
165            }
166
167            fn fory_write_data(&self, context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
168                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
169                fory_core::serializer::write_box_any(any_ref, context, false, false, false)
170            }
171
172            fn fory_write_data_generic(&self, context: &mut fory_core::WriteContext, has_generics: bool) -> Result<(), fory_core::Error> {
173                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
174                fory_core::serializer::write_box_any(any_ref, context, false, false, has_generics)
175            }
176
177            fn fory_type_id_dyn(&self, type_resolver: &fory_core::TypeResolver) -> Result<u32, fory_core::Error> {
178                let any_ref = <dyn $trait_name as fory_core::Serializer>::as_any(&**self);
179                let concrete_type_id = any_ref.type_id();
180                type_resolver
181                    .get_fory_type_id(concrete_type_id)
182                    .ok_or_else(|| fory_core::Error::type_error("Type not registered for trait object"))
183            }
184
185            fn fory_is_polymorphic() -> bool {
186                true
187            }
188
189            fn fory_write_type_info(_context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
190                $crate::not_allowed!("fory_write_type_info should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
191            }
192
193            fn fory_read_type_info(_context: &mut fory_core::ReadContext) -> Result<(), fory_core::Error> {
194                $crate::not_allowed!("fory_read_type_info should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
195            }
196
197            fn fory_read(context: &mut fory_core::ReadContext, read_ref_info: bool, read_type_info: bool) -> Result<Self, fory_core::Error> {
198                let boxed_any = fory_core::serializer::read_box_any(context, read_ref_info, read_type_info, None)?;
199                $(
200                    if boxed_any.is::<$impl_type>() {
201                        let concrete = boxed_any.downcast::<$impl_type>()
202                            .map_err(|_| fory_core::Error::type_error("Downcast failed"))?;
203                        let ptr = Box::new(*concrete);
204                        return Ok(Self::from(ptr));
205                    }
206                )*
207                Err(fory_core::Error::type_error(
208                    format!("Deserialized type does not implement trait {}", stringify!($trait_name))
209                ))
210            }
211
212            fn fory_read_with_type_info(
213                context: &mut fory_core::ReadContext,
214                read_ref_info: bool,
215                type_info: std::rc::Rc<fory_core::TypeInfo>,
216            ) -> Result<Self, fory_core::Error>
217            where
218                Self: Sized + fory_core::ForyDefault,
219            {
220                let boxed_any = fory_core::serializer::read_box_any(context, read_ref_info, false, Some(type_info))?;
221                $(
222                    if boxed_any.is::<$impl_type>() {
223                        let concrete = boxed_any.downcast::<$impl_type>()
224                            .map_err(|_| fory_core::Error::type_error("Downcast failed"))?;
225                        let ptr = Box::new(*concrete);
226                        return Ok(Self::from(ptr));
227                    }
228                )*
229                Err(fory_core::Error::type_error(
230                    format!("Deserialized type does not implement trait {}", stringify!($trait_name))
231                ))
232            }
233
234            fn fory_read_data(_context: &mut fory_core::ReadContext) -> Result<Self, fory_core::Error> {
235                // This should not be called for polymorphic types like Box<dyn Trait>
236                // The fory_read method handles the polymorphic dispatch
237                $crate::not_allowed!("fory_read_data should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
238            }
239
240            fn fory_get_type_id(_type_resolver: &fory_core::TypeResolver) -> Result<u32, fory_core::Error> {
241                $crate::not_allowed!("fory_get_type_id should not be called directly on polymorphic Box<dyn {}> trait object", stringify!($trait_name))
242            }
243
244            fn fory_static_type_id() -> fory_core::TypeId {
245                fory_core::TypeId::UNKNOWN
246            }
247
248            fn fory_reserved_space() -> usize {
249                $crate::types::SIZE_OF_REF_AND_TYPE
250            }
251
252            fn fory_concrete_type_id(&self) -> std::any::TypeId {
253                <dyn $trait_name as fory_core::Serializer>::as_any(&**self).type_id()
254            }
255
256            fn as_any(&self) -> &dyn std::any::Any {
257                <dyn $trait_name as fory_core::Serializer>::as_any(&**self)
258            }
259        }
260    };
261
262    // Helper to get first type for Default impl
263    (@first_type $first_type:ty $(, $rest:ty)*) => {
264        $first_type
265    };
266}
267
268/// Unified macro to generate smart pointer wrapper types for traits
269/// Supports both Rc and Arc pointer types
270#[macro_export]
271macro_rules! generate_smart_pointer_wrapper {
272    ($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),+ $(,)?) => {
273        $crate::paste::paste! {
274            #[derive(Clone)]
275            pub(crate) struct [<$trait_name $ptr_name>]($ptr_path<dyn $trait_name>);
276
277            impl [<$trait_name $ptr_name>] {
278                pub(crate) fn new(inner: $ptr_path<dyn $trait_name>) -> Self {
279                    Self(inner)
280                }
281
282                pub(crate) fn into_inner(self) -> $ptr_path<dyn $trait_name> {
283                    self.0
284                }
285
286                pub(crate) fn unwrap(self) -> $ptr_path<dyn $trait_name> {
287                    self.0
288                }
289
290                pub(crate) fn as_ref(&self) -> &dyn $trait_name {
291                    &*self.0
292                }
293            }
294
295            impl std::ops::Deref for [<$trait_name $ptr_name>] {
296                type Target = dyn $trait_name;
297
298                fn deref(&self) -> &Self::Target {
299                    &*self.0
300                }
301            }
302
303            impl std::ops::DerefMut for [<$trait_name $ptr_name>] {
304                fn deref_mut(&mut self) -> &mut Self::Target {
305                    $get_mut(&mut self.0)
306                        .expect(&format!("Cannot get mutable reference to {} with multiple strong references", stringify!($ptr_name)))
307                }
308            }
309
310            impl From<$ptr_path<dyn $trait_name>> for [<$trait_name $ptr_name>] {
311                fn from(ptr: $ptr_path<dyn $trait_name>) -> Self {
312                    Self::new(ptr)
313                }
314            }
315
316            impl From<[<$trait_name $ptr_name>]> for $ptr_path<dyn $trait_name> {
317                fn from(wrapper: [<$trait_name $ptr_name>]) -> Self {
318                    wrapper.into_inner()
319                }
320            }
321
322            impl std::default::Default for [<$trait_name $ptr_name>] {
323                fn default() -> Self {
324                    Self($ptr_path::new(<$crate::register_trait_type!(@first_type $($impl_type),+) as std::default::Default>::default()))
325                }
326            }
327
328            impl $crate::serializer::ForyDefault for [<$trait_name $ptr_name>] {
329                fn fory_default() -> Self {
330                    Self($ptr_path::new(<$crate::register_trait_type!(@first_type $($impl_type),+) as std::default::Default>::default()))
331                }
332            }
333
334            impl std::fmt::Debug for [<$trait_name $ptr_name>] {
335                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
336                    let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
337                    $(
338                        if let Some(concrete) = any_obj.downcast_ref::<$impl_type>() {
339                            return write!(f, concat!(stringify!($trait_name), stringify!($ptr_name), "({:?})"), concrete);
340                        }
341                    )*
342                    write!(f, concat!(stringify!($trait_name), stringify!($ptr_name), "({:p})"), &*self.0)
343                }
344            }
345
346            $crate::impl_smart_pointer_serializer!(
347                [<$trait_name $ptr_name>],
348                $ptr_path<dyn $trait_name>,
349                $ptr_path::new,
350                $trait_name,
351                $try_write_ref,
352                $get_ref,
353                $store_ref,
354                $($impl_type),+
355            );
356        }
357    };
358}
359
360/// Macro to read smart pointer trait objects (`Rc<dyn Trait>,` `Arc<dyn Trait>`)
361/// This macro handles ref tracking and directly constructs the trait object from concrete types
362#[macro_export]
363macro_rules! read_ptr_trait_object {
364    ($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),+) => {{
365        let ref_flag = if $read_ref_info {
366            $context.ref_reader.read_ref_flag(&mut $context.reader)?
367        } else {
368            fory_core::RefFlag::NotNullValue
369        };
370        match ref_flag {
371            fory_core::RefFlag::Null => Err(fory_core::Error::invalid_ref(format!("smart pointer to dyn {} cannot be null", stringify!($trait_name)))),
372            fory_core::RefFlag::Ref => {
373                let ref_id = $context.ref_reader.read_ref_id(&mut $context.reader)?;
374                let ptr_ref = $context.ref_reader.$get_ref::<dyn $trait_name>(ref_id)
375                    .ok_or_else(|| fory_core::Error::invalid_data(format!("dyn {} reference {} not found", stringify!($trait_name), ref_id)))?;
376                Ok(Self::from(ptr_ref))
377            }
378            fory_core::RefFlag::NotNullValue => {
379                $context.inc_depth()?;
380                let typeinfo = if $read_type_info {
381                    $context.read_any_typeinfo()?
382                } else {
383                    $type_info.ok_or_else(|| fory_core::Error::type_error("No type info found for read"))?
384                };
385                let fory_type_id = typeinfo.get_type_id();
386                $(
387                    if let Some(registered_type_id) = $context.get_type_resolver().get_fory_type_id(std::any::TypeId::of::<$impl_type>()) {
388                        if fory_type_id == registered_type_id {
389                            let concrete_obj = <$impl_type as fory_core::Serializer>::fory_read_data($context)?;
390                            $context.dec_depth();
391                            let ptr = $constructor_expr(concrete_obj) as $pointer_type;
392                            return Ok(Self::from(ptr));
393                        }
394                    }
395                )*
396                $context.dec_depth();
397                Err(fory_core::Error::type_error(
398                    format!("Type ID {} not registered for trait {}", fory_type_id, stringify!($trait_name))
399                ))
400            }
401            fory_core::RefFlag::RefValue => {
402                $context.inc_depth()?;
403                let typeinfo = if $read_type_info {
404                    $context.read_any_typeinfo()?
405                } else {
406                    $type_info.ok_or_else(|| fory_core::Error::type_error("No type info found for read"))?
407                };
408                let fory_type_id = typeinfo.get_type_id();
409                $(
410                    if let Some(registered_type_id) = $context.get_type_resolver().get_fory_type_id(std::any::TypeId::of::<$impl_type>()) {
411                        if fory_type_id == registered_type_id {
412                            let concrete_obj = <$impl_type as fory_core::Serializer>::fory_read_data($context)?;
413                            $context.dec_depth();
414                            let ptr = $constructor_expr(concrete_obj) as $pointer_type;
415                            let wrapper = Self::from(ptr.clone());
416                            $context.ref_reader.$store_ref(ptr);
417                            return Ok(wrapper);
418                        }
419                    }
420                )*
421                $context.dec_depth();
422                Err(fory_core::Error::type_error(
423                    format!("Type ID {} not registered for trait {}", fory_type_id, stringify!($trait_name))
424                ))
425            }
426        }
427    }};
428}
429
430/// Shared serializer implementation for smart pointer wrappers
431#[macro_export]
432macro_rules! impl_smart_pointer_serializer {
433    ($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),+) => {
434        impl fory_core::Serializer for $wrapper_name {
435            fn fory_write(&self, context: &mut fory_core::WriteContext, write_ref_info: bool, write_type_info: bool, has_generics: bool) -> Result<(), fory_core::Error> {
436                if !write_ref_info || !context.ref_writer.$try_write_ref(&mut context.writer, &self.0) {
437                    let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
438                    let concrete_type_id = any_obj.type_id();
439                    let typeinfo = if write_type_info {
440                         context.write_any_typeinfo(fory_core::TypeId::UNKNOWN as u32, concrete_type_id)?
441                    } else {
442                        context.get_type_info(&concrete_type_id)?
443                    };
444                    let serializer_fn = typeinfo.get_harness().get_write_data_fn();
445                    serializer_fn(any_obj, context, has_generics)?;
446                }
447                Ok(())
448            }
449
450            fn fory_write_data(&self, context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
451                let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
452                $crate::downcast_and_serialize!(any_obj, context, $trait_name, $($impl_type),+)
453            }
454
455            fn fory_read(context: &mut fory_core::ReadContext, read_ref_info: bool, read_type_info: bool) -> Result<Self, fory_core::Error> {
456                $crate::read_ptr_trait_object!(
457                    context,
458                    read_ref_info,
459                    read_type_info,
460                    None,
461                    $pointer_type,
462                    $trait_name,
463                    $constructor_expr,
464                    $get_ref,
465                    $store_ref,
466                    $($impl_type),+
467                )
468            }
469
470            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> {
471                $crate::read_ptr_trait_object!(
472                    context,
473                    read_ref_info,
474                    false,
475                    Some(type_info),
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_data(context: &mut fory_core::ReadContext) -> Result<Self, fory_core::Error> {
486                $crate::not_allowed!("fory_read_data should not be called directly on polymorphic {}<dyn {}> trait object", stringify!($ptr_path), stringify!($trait_name))
487            }
488
489            fn fory_get_type_id(_type_resolver: &fory_core::TypeResolver) -> Result<u32, fory_core::Error> {
490                Ok(fory_core::TypeId::STRUCT as u32)
491            }
492
493            fn fory_static_type_id() -> fory_core::TypeId {
494                fory_core::TypeId::UNKNOWN
495            }
496
497            fn fory_write_type_info(_context: &mut fory_core::WriteContext) -> Result<(), fory_core::Error> {
498                Ok(())
499            }
500
501            fn fory_read_type_info(_context: &mut fory_core::ReadContext) -> Result<(), fory_core::Error>  {
502                Ok(())
503            }
504
505            fn fory_is_polymorphic() -> bool {
506                true
507            }
508
509            fn fory_is_shared_ref() -> bool {
510                true
511            }
512
513            fn fory_type_id_dyn(&self, type_resolver: &fory_core::TypeResolver) -> Result<u32, fory_core::Error> {
514                let any_obj = <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0);
515                let concrete_type_id = any_obj.type_id();
516                type_resolver
517                    .get_fory_type_id(concrete_type_id)
518                    .ok_or_else(|| fory_core::Error::type_error("Type not registered for trait object"))
519            }
520
521            fn fory_concrete_type_id(&self) -> std::any::TypeId {
522                <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0).type_id()
523            }
524
525            fn as_any(&self) -> &dyn std::any::Any {
526                <dyn $trait_name as fory_core::Serializer>::as_any(&*self.0)
527            }
528        }
529    };
530}
531
532/// Helper macros for automatic conversions in derive code
533/// These are used by fory-derive to generate transparent conversions
534///
535/// Convert field of type `Rc<dyn Trait>` to wrapper for serialization
536#[macro_export]
537macro_rules! wrap_rc {
538    ($field:expr, $trait_name:ident) => {
539        $crate::paste::paste! {
540            [<$trait_name Rc>]::from($field)
541        }
542    };
543}
544
545/// Convert wrapper back to `Rc<dyn Trait>` for deserialization
546#[macro_export]
547macro_rules! unwrap_rc {
548    ($wrapper:expr, $trait_name:ident) => {
549        std::rc::Rc::<dyn $trait_name>::from($wrapper)
550    };
551}
552
553/// Convert `Arc<dyn Trait>` to wrapper for serialization
554#[macro_export]
555macro_rules! wrap_arc {
556    ($field:expr, $trait_name:ident) => {
557        $crate::paste::paste! {
558            [<$trait_name Arc>]::from($field)
559        }
560    };
561}
562
563/// Convert `Vec<Rc<dyn Trait>>` to `Vec<wrapper>` for serialization
564#[macro_export]
565macro_rules! wrap_vec_rc {
566    ($vec:expr, $trait_name:ident) => {
567        $crate::paste::paste! {
568            $vec.into_iter().map(|item| [<$trait_name Rc>]::from(item)).collect()
569        }
570    };
571}
572
573impl Default for Box<dyn Serializer> {
574    fn default() -> Self {
575        Box::new(0)
576    }
577}
578
579impl ForyDefault for Box<dyn Serializer> {
580    fn fory_default() -> Self {
581        Box::new(0)
582    }
583}
584
585impl Serializer for Box<dyn Serializer> {
586    fn fory_concrete_type_id(&self) -> std::any::TypeId {
587        (**self).fory_concrete_type_id()
588    }
589
590    fn fory_write(
591        &self,
592        context: &mut WriteContext,
593        write_ref_info: bool,
594        write_type_info: bool,
595        has_generics: bool,
596    ) -> Result<(), Error> {
597        if write_ref_info {
598            context.writer.write_i8(RefFlag::NotNullValue as i8);
599        }
600        let fory_type_id_dyn = self.fory_type_id_dyn(context.get_type_resolver())?;
601        let concrete_type_id = (**self).fory_concrete_type_id();
602        if write_type_info {
603            context.write_any_typeinfo(fory_type_id_dyn, concrete_type_id)?;
604        };
605        self.fory_write_data_generic(context, has_generics)
606    }
607
608    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
609        self.fory_write_data_generic(context, false)
610    }
611
612    fn fory_write_data_generic(
613        &self,
614        context: &mut WriteContext,
615        has_generics: bool,
616    ) -> Result<(), Error> {
617        (**self).fory_write_data_generic(context, has_generics)
618    }
619
620    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<u32, Error> {
621        (**self).fory_type_id_dyn(type_resolver)
622    }
623
624    fn as_any(&self) -> &dyn std::any::Any {
625        (**self).as_any()
626    }
627
628    fn fory_is_polymorphic() -> bool {
629        true
630    }
631
632    fn fory_write_type_info(_context: &mut WriteContext) -> Result<(), Error> {
633        Err(Error::not_allowed(
634            "Box<dyn Serializer> is polymorphic - can's write type info statically",
635        ))
636    }
637
638    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
639        context.read_any_typeinfo()?;
640        Ok(())
641    }
642
643    fn fory_read(
644        context: &mut ReadContext,
645        read_ref_info: bool,
646        read_type_info: bool,
647    ) -> Result<Self, Error> {
648        read_box_seralizer(context, read_ref_info, read_type_info, None)
649    }
650
651    fn fory_read_with_type_info(
652        context: &mut ReadContext,
653        read_ref_info: bool,
654        type_info: Rc<TypeInfo>,
655    ) -> Result<Self, Error>
656    where
657        Self: Sized + ForyDefault,
658    {
659        read_box_seralizer(context, read_ref_info, false, Some(type_info))
660    }
661
662    fn fory_read_data(_context: &mut ReadContext) -> Result<Self, Error> {
663        Err(Error::not_allowed(
664            "fory_read_data should not be called directly on Box<dyn Serializer>",
665        ))
666    }
667}
668
669fn read_box_seralizer(
670    context: &mut ReadContext,
671    read_ref_info: bool,
672    read_type_info: bool,
673    type_info: Option<Rc<TypeInfo>>,
674) -> Result<Box<dyn Serializer>, Error> {
675    context.inc_depth()?;
676    let ref_flag = if read_ref_info {
677        context.reader.read_i8()?
678    } else {
679        RefFlag::NotNullValue as i8
680    };
681    if ref_flag != RefFlag::NotNullValue as i8 {
682        return Err(Error::invalid_data(
683            "Expected NotNullValue for Box<dyn Serializer>",
684        ));
685    }
686    let typeinfo = if let Some(type_info) = type_info {
687        type_info
688    } else {
689        ensure!(
690            read_type_info,
691            Error::invalid_data("Type info must be read for Box<dyn Serializer>")
692        );
693        context.read_any_typeinfo()?
694    };
695    let harness = typeinfo.get_harness();
696    let boxed_any = harness.get_read_data_fn()(context)?;
697    let trait_object = harness.get_to_serializer()(boxed_any)?;
698    context.dec_depth();
699    Ok(trait_object)
700}