Skip to main content

fory_core/serializer/
any.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
18use crate::context::{ReadContext, WriteContext};
19use crate::ensure;
20use crate::error::Error;
21use crate::resolver::{RefFlag, RefMode};
22use crate::resolver::{TypeInfo, TypeResolver};
23use crate::serializer::util::write_dyn_data_generic;
24use crate::serializer::{ForyDefault, Serializer};
25use crate::type_id::TypeId;
26use std::any::Any;
27use std::rc::Rc;
28use std::sync::Arc;
29
30#[inline(always)]
31fn resolve_registered_type_id(
32    type_resolver: &TypeResolver,
33    concrete_type_id: std::any::TypeId,
34) -> Result<TypeId, Error> {
35    type_resolver
36        .get_fory_type_id(concrete_type_id)
37        .ok_or_else(|| Error::type_error("Type not registered"))
38}
39
40#[inline]
41fn is_erased_any_container_type(type_id: TypeId) -> bool {
42    matches!(
43        type_id,
44        TypeId::LIST
45            | TypeId::SET
46            | TypeId::MAP
47            | TypeId::BINARY
48            | TypeId::ARRAY
49            | TypeId::BOOL_ARRAY
50            | TypeId::INT8_ARRAY
51            | TypeId::INT16_ARRAY
52            | TypeId::INT32_ARRAY
53            | TypeId::INT64_ARRAY
54            | TypeId::UINT8_ARRAY
55            | TypeId::UINT16_ARRAY
56            | TypeId::UINT32_ARRAY
57            | TypeId::UINT64_ARRAY
58            | TypeId::FLOAT8_ARRAY
59            | TypeId::FLOAT16_ARRAY
60            | TypeId::BFLOAT16_ARRAY
61            | TypeId::FLOAT32_ARRAY
62            | TypeId::FLOAT64_ARRAY
63            | TypeId::U128_ARRAY
64            | TypeId::INT128_ARRAY
65            | TypeId::USIZE_ARRAY
66            | TypeId::ISIZE_ARRAY
67    )
68}
69
70#[cold]
71#[inline(never)]
72fn unsupported_erased_any_container() -> Error {
73    Error::type_error(
74        "List-, map-, and set-like containers cannot be used as top-level erased Any \
75        payloads via Box<dyn Any>, Rc<dyn Any>, or Arc<dyn Any + Send + Sync>. This \
76        includes Vec<T>, byte and numeric vectors, LinkedList<T>, HashSet<T>, and \
77        HashMap<K, V>. Wrap the container in a registered struct, enum, or union and \
78        use that wrapper as the erased payload.",
79    )
80}
81
82#[cold]
83#[inline(never)]
84fn erased_any_type_info_error(err: Error) -> Error {
85    Error::type_error(format!(
86        "{err}. Erased Any payloads require a registered concrete non-container type. \
87        Top-level list-, map-, and set-like containers such as Vec<T>, LinkedList<T>, \
88        HashSet<T>, and HashMap<K, V> are unsupported; wrap the container in a \
89        registered struct, enum, or union."
90    ))
91}
92
93#[inline]
94pub(crate) fn check_erased_any_payload_type(type_info: &TypeInfo) -> Result<(), Error> {
95    if is_erased_any_container_type(type_info.get_type_id()) {
96        return Err(unsupported_erased_any_container());
97    }
98    Ok(())
99}
100
101#[inline]
102fn get_erased_any_type_info(
103    context: &WriteContext,
104    concrete_type_id: &std::any::TypeId,
105) -> Result<Rc<TypeInfo>, Error> {
106    let type_info = context
107        .get_type_info(concrete_type_id)
108        .map_err(erased_any_type_info_error)?;
109    check_erased_any_payload_type(&type_info)?;
110    Ok(type_info)
111}
112
113#[inline]
114fn write_erased_any_type_info(
115    context: &mut WriteContext,
116    concrete_type_id: std::any::TypeId,
117) -> Result<Rc<TypeInfo>, Error> {
118    let type_info = context
119        .write_any_type_info(TypeId::UNKNOWN as u32, concrete_type_id)
120        .map_err(erased_any_type_info_error)?;
121    check_erased_any_payload_type(&type_info)?;
122    Ok(type_info)
123}
124
125/// Helper function to deserialize to `Box<dyn Any>`
126pub fn deserialize_any_box(context: &mut ReadContext) -> Result<Box<dyn Any>, Error> {
127    context.inc_depth()?;
128    let ref_flag = context.reader.read_i8()?;
129    if ref_flag != RefFlag::NotNullValue as i8 {
130        return Err(Error::invalid_ref("Expected NotNullValue for Box<dyn Any>"));
131    }
132    let typeinfo = context.read_any_type_info()?;
133    check_erased_any_payload_type(&typeinfo)?;
134    let result = typeinfo
135        .get_harness()
136        .read_polymorphic_data(context, &typeinfo);
137    context.dec_depth();
138    result
139}
140
141impl ForyDefault for Box<dyn Any> {
142    fn fory_default() -> Self {
143        Box::new(())
144    }
145}
146
147impl Serializer for Box<dyn Any> {
148    fn fory_write(
149        &self,
150        context: &mut WriteContext,
151        ref_mode: RefMode,
152        write_type_info: bool,
153        has_generics: bool,
154    ) -> Result<(), Error> {
155        write_box_any(
156            self.as_ref(),
157            context,
158            ref_mode,
159            write_type_info,
160            has_generics,
161        )
162    }
163
164    fn fory_write_data_generic(
165        &self,
166        context: &mut WriteContext,
167        has_generics: bool,
168    ) -> Result<(), Error> {
169        let concrete_type_id = (**self).type_id();
170        let typeinfo = get_erased_any_type_info(context, &concrete_type_id)?;
171        let serializer_fn = typeinfo.get_harness().get_write_data_fn();
172        serializer_fn(&**self, context, has_generics)
173    }
174
175    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
176        self.fory_write_data_generic(context, false)
177    }
178
179    fn fory_read(
180        context: &mut ReadContext,
181        ref_mode: RefMode,
182        read_type_info: bool,
183    ) -> Result<Self, Error> {
184        read_box_any(context, ref_mode, read_type_info, None)
185    }
186
187    fn fory_read_with_type_info(
188        context: &mut ReadContext,
189        ref_mode: RefMode,
190        type_info: Rc<TypeInfo>,
191    ) -> Result<Self, Error>
192    where
193        Self: Sized + ForyDefault,
194    {
195        read_box_any(context, ref_mode, false, Some(type_info))
196    }
197
198    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
199        Err(Error::not_allowed(
200            "fory_read_data should not be called directly on polymorphic Box<dyn Any> trait object",
201        ))
202    }
203
204    fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
205        Err(Error::type_error(
206            "Box<dyn Any> has no static type ID - use fory_type_id_dyn",
207        ))
208    }
209
210    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
211        resolve_registered_type_id(type_resolver, (**self).type_id())
212    }
213
214    fn fory_concrete_type_id(&self) -> std::any::TypeId {
215        (**self).type_id()
216    }
217
218    fn fory_is_polymorphic() -> bool {
219        true
220    }
221
222    fn fory_is_shared_ref() -> bool {
223        false
224    }
225
226    fn fory_static_type_id() -> TypeId {
227        TypeId::UNKNOWN
228    }
229
230    fn fory_write_type_info(_context: &mut WriteContext) -> Result<(), Error> {
231        // Box<dyn Any> is polymorphic - type info is written per element
232        Ok(())
233    }
234
235    fn fory_read_type_info(_context: &mut ReadContext) -> Result<(), Error> {
236        // Box<dyn Any> is polymorphic - type info is read per element
237        Ok(())
238    }
239
240    fn as_any(&self) -> &dyn Any {
241        &**self
242    }
243}
244
245pub fn write_box_any(
246    value: &dyn Any,
247    context: &mut WriteContext,
248    ref_mode: RefMode,
249    write_type_info: bool,
250    has_generics: bool,
251) -> Result<(), Error> {
252    if ref_mode != RefMode::None {
253        context.writer.write_i8(RefFlag::NotNullValue as i8);
254    }
255    let concrete_type_id = value.type_id();
256    let typeinfo = if write_type_info {
257        write_erased_any_type_info(context, concrete_type_id)?
258    } else {
259        get_erased_any_type_info(context, &concrete_type_id)?
260    };
261    let serializer_fn = typeinfo.get_harness().get_write_data_fn();
262    serializer_fn(value, context, has_generics)
263}
264
265pub fn read_box_any(
266    context: &mut ReadContext,
267    ref_mode: RefMode,
268    read_type_info: bool,
269    type_info: Option<Rc<TypeInfo>>,
270) -> Result<Box<dyn Any>, Error> {
271    context.inc_depth()?;
272    let ref_flag = if ref_mode != RefMode::None {
273        context.reader.read_i8()?
274    } else {
275        RefFlag::NotNullValue as i8
276    };
277    if ref_flag != RefFlag::NotNullValue as i8 {
278        return Err(Error::invalid_data(
279            "Expected NotNullValue for Box<dyn Any>",
280        ));
281    }
282    let typeinfo = if let Some(type_info) = type_info {
283        type_info
284    } else {
285        ensure!(
286            read_type_info,
287            Error::invalid_data("Type info must be read for Box<dyn Any>")
288        );
289        context.read_any_type_info()?
290    };
291    check_erased_any_payload_type(&typeinfo)?;
292    let result = typeinfo
293        .get_harness()
294        .read_polymorphic_data(context, &typeinfo);
295    context.dec_depth();
296    result
297}
298
299impl ForyDefault for Rc<dyn Any> {
300    fn fory_default() -> Self {
301        Rc::new(())
302    }
303}
304
305impl Serializer for Rc<dyn Any> {
306    fn fory_write(
307        &self,
308        context: &mut WriteContext,
309        ref_mode: RefMode,
310        write_type_info: bool,
311        has_generics: bool,
312    ) -> Result<(), Error> {
313        if ref_mode == RefMode::None
314            || !context
315                .ref_writer
316                .try_write_rc_ref(&mut context.writer, self)
317        {
318            let concrete_type_id: std::any::TypeId = (**self).type_id();
319            let typeinfo = if write_type_info {
320                write_erased_any_type_info(context, concrete_type_id)?
321            } else {
322                get_erased_any_type_info(context, &concrete_type_id)?
323            };
324            let write_data_fn = typeinfo.get_harness().get_write_data_fn();
325            write_data_fn(&**self, context, has_generics)?;
326        }
327        Ok(())
328    }
329
330    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
331        write_dyn_data_generic(self, context, false)
332    }
333
334    fn fory_write_data_generic(
335        &self,
336        context: &mut WriteContext,
337        has_generics: bool,
338    ) -> Result<(), Error> {
339        write_dyn_data_generic(self, context, has_generics)
340    }
341
342    fn fory_read(
343        context: &mut ReadContext,
344        ref_mode: RefMode,
345        read_type_info: bool,
346    ) -> Result<Self, Error> {
347        read_rc_any(context, ref_mode, read_type_info, None)
348    }
349
350    fn fory_read_with_type_info(
351        context: &mut ReadContext,
352        ref_mode: RefMode,
353        type_info: Rc<TypeInfo>,
354    ) -> Result<Self, Error>
355    where
356        Self: Sized + ForyDefault,
357    {
358        read_rc_any(context, ref_mode, false, Some(type_info))
359    }
360
361    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
362        Err(Error::not_allowed(
363            "fory_read_data should not be called directly on polymorphic Rc<dyn Any> trait object",
364        ))
365    }
366
367    fn fory_get_type_id(_: &TypeResolver) -> Result<TypeId, Error> {
368        Err(Error::type_error(
369            "Rc<dyn Any> has no static type ID - use fory_type_id_dyn",
370        ))
371    }
372
373    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
374        resolve_registered_type_id(type_resolver, (**self).type_id())
375    }
376
377    fn fory_concrete_type_id(&self) -> std::any::TypeId {
378        (**self).type_id()
379    }
380
381    fn fory_is_shared_ref() -> bool {
382        true
383    }
384    fn fory_is_polymorphic() -> bool {
385        true
386    }
387
388    fn fory_static_type_id() -> TypeId {
389        TypeId::UNKNOWN
390    }
391
392    fn fory_write_type_info(_context: &mut WriteContext) -> Result<(), Error> {
393        // Rc<dyn Any> is polymorphic - type info is written per element
394        Ok(())
395    }
396
397    fn fory_read_type_info(_context: &mut ReadContext) -> Result<(), Error> {
398        // Rc<dyn Any> is polymorphic - type info is read per element
399        Ok(())
400    }
401
402    fn as_any(&self) -> &dyn Any {
403        &**self
404    }
405}
406
407pub fn read_rc_any(
408    context: &mut ReadContext,
409    ref_mode: RefMode,
410    read_type_info: bool,
411    type_info: Option<Rc<TypeInfo>>,
412) -> Result<Rc<dyn Any>, Error> {
413    let ref_flag = if ref_mode != RefMode::None {
414        context.ref_reader.read_ref_flag(&mut context.reader)?
415    } else {
416        RefFlag::NotNullValue
417    };
418    match ref_flag {
419        RefFlag::Null => Err(Error::invalid_ref("Rc<dyn Any> cannot be null")),
420        RefFlag::Ref => {
421            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
422            context
423                .ref_reader
424                .get_rc_ref::<dyn Any>(ref_id)
425                .ok_or_else(|| {
426                    Error::invalid_data(format!("Rc<dyn Any> reference {} not found", ref_id))
427                })
428        }
429        RefFlag::NotNullValue => {
430            context.inc_depth()?;
431            let typeinfo = if read_type_info {
432                context.read_any_type_info()?
433            } else {
434                type_info.ok_or_else(|| Error::type_error("No type info found for read"))?
435            };
436            check_erased_any_payload_type(&typeinfo)?;
437            let boxed = typeinfo
438                .get_harness()
439                .read_polymorphic_data(context, &typeinfo)?;
440            context.dec_depth();
441            Ok(Rc::<dyn Any>::from(boxed))
442        }
443        RefFlag::RefValue => {
444            let ref_id = context.ref_reader.reserve_ref_id();
445            context.inc_depth()?;
446            let typeinfo = if read_type_info {
447                context.read_any_type_info()?
448            } else {
449                type_info.ok_or_else(|| Error::type_error("No type info found for read"))?
450            };
451            check_erased_any_payload_type(&typeinfo)?;
452            let boxed = typeinfo
453                .get_harness()
454                .read_polymorphic_data(context, &typeinfo)?;
455            context.dec_depth();
456            let rc: Rc<dyn Any> = Rc::from(boxed);
457            context.ref_reader.store_rc_ref_at(ref_id, rc.clone());
458            Ok(rc)
459        }
460    }
461}
462
463impl ForyDefault for Arc<dyn Any + Send + Sync> {
464    fn fory_default() -> Self {
465        Arc::new(())
466    }
467}
468
469impl Serializer for Arc<dyn Any + Send + Sync> {
470    fn fory_write(
471        &self,
472        context: &mut WriteContext,
473        ref_mode: RefMode,
474        write_type_info: bool,
475        has_generics: bool,
476    ) -> Result<(), Error> {
477        if ref_mode == RefMode::None
478            || !context
479                .ref_writer
480                .try_write_arc_ref(&mut context.writer, self)
481        {
482            let value: &dyn Any = self.as_ref();
483            let concrete_type_id: std::any::TypeId = value.type_id();
484            let typeinfo = if write_type_info {
485                write_erased_any_type_info(context, concrete_type_id)?
486            } else {
487                get_erased_any_type_info(context, &concrete_type_id)?
488            };
489            let serializer_fn = typeinfo.get_harness().get_write_data_fn();
490            serializer_fn(value, context, has_generics)?;
491        }
492        Ok(())
493    }
494
495    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
496        write_dyn_data_generic(self, context, false)
497    }
498
499    fn fory_write_data_generic(
500        &self,
501        context: &mut WriteContext,
502        has_generics: bool,
503    ) -> Result<(), Error> {
504        write_dyn_data_generic(self, context, has_generics)
505    }
506
507    fn fory_read(
508        context: &mut ReadContext,
509        ref_mode: RefMode,
510        read_type_info: bool,
511    ) -> Result<Self, Error> {
512        read_arc_any(context, ref_mode, read_type_info, None)
513    }
514
515    fn fory_read_with_type_info(
516        context: &mut ReadContext,
517        ref_mode: RefMode,
518        type_info: Rc<TypeInfo>,
519    ) -> Result<Self, Error>
520    where
521        Self: Sized + ForyDefault,
522    {
523        read_arc_any(context, ref_mode, false, Some(type_info))
524    }
525
526    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
527        Err(Error::not_allowed(
528            "fory_read_data should not be called directly on polymorphic Arc<dyn Any + Send + Sync> trait object"
529        ))
530    }
531
532    fn fory_get_type_id(_type_resolver: &TypeResolver) -> Result<TypeId, Error> {
533        Err(Error::type_error(
534            "Arc<dyn Any + Send + Sync> has no static type ID - use fory_type_id_dyn",
535        ))
536    }
537
538    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
539        resolve_registered_type_id(type_resolver, self.as_ref().type_id())
540    }
541
542    fn fory_concrete_type_id(&self) -> std::any::TypeId {
543        self.as_ref().type_id()
544    }
545
546    fn fory_is_polymorphic() -> bool {
547        true
548    }
549
550    fn fory_is_shared_ref() -> bool {
551        true
552    }
553    fn fory_static_type_id() -> TypeId {
554        TypeId::UNKNOWN
555    }
556
557    fn fory_write_type_info(_context: &mut WriteContext) -> Result<(), Error> {
558        // Arc<dyn Any + Send + Sync> is polymorphic - type info is written per element
559        Ok(())
560    }
561
562    fn fory_read_type_info(_context: &mut ReadContext) -> Result<(), Error> {
563        // Arc<dyn Any + Send + Sync> is polymorphic - type info is read per element
564        Ok(())
565    }
566
567    fn fory_read_data_as_send_sync_any(
568        context: &mut ReadContext,
569    ) -> Result<Box<dyn Any + Send + Sync>, Error>
570    where
571        Self: Sized + ForyDefault,
572    {
573        Ok(crate::serializer::box_send_sync(read_arc_any(
574            context,
575            RefMode::None,
576            true,
577            None,
578        )?))
579    }
580
581    fn as_any(&self) -> &dyn Any {
582        self.as_ref()
583    }
584}
585
586pub fn read_arc_any(
587    context: &mut ReadContext,
588    ref_mode: RefMode,
589    read_type_info: bool,
590    type_info: Option<Rc<TypeInfo>>,
591) -> Result<Arc<dyn Any + Send + Sync>, Error> {
592    let ref_flag = if ref_mode != RefMode::None {
593        context.ref_reader.read_ref_flag(&mut context.reader)?
594    } else {
595        RefFlag::NotNullValue
596    };
597    match ref_flag {
598        RefFlag::Null => Err(Error::invalid_ref(
599            "Arc<dyn Any + Send + Sync> cannot be null",
600        )),
601        RefFlag::Ref => {
602            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
603            context
604                .ref_reader
605                .get_arc_ref::<dyn Any + Send + Sync>(ref_id)
606                .ok_or_else(|| {
607                    Error::invalid_data(format!(
608                        "Arc<dyn Any + Send + Sync> reference {} not found",
609                        ref_id
610                    ))
611                })
612        }
613        RefFlag::NotNullValue => {
614            context.inc_depth()?;
615            let typeinfo = if read_type_info {
616                context.read_any_type_info()?
617            } else {
618                type_info.ok_or_else(|| {
619                    Error::type_error("No type info found for read Arc<dyn Any + Send + Sync>")
620                })?
621            };
622            check_erased_any_payload_type(&typeinfo)?;
623            let boxed = typeinfo
624                .get_harness()
625                .read_polymorphic_data_as_send_sync_any(context, &typeinfo)?;
626            context.dec_depth();
627            Ok(Arc::<dyn Any + Send + Sync>::from(boxed))
628        }
629        RefFlag::RefValue => {
630            let ref_id = context.ref_reader.reserve_ref_id();
631            context.inc_depth()?;
632            let typeinfo = if read_type_info {
633                context.read_any_type_info()?
634            } else {
635                type_info.ok_or_else(|| {
636                    Error::type_error("No type info found for read Arc<dyn Any + Send + Sync>")
637                })?
638            };
639            check_erased_any_payload_type(&typeinfo)?;
640            let boxed = typeinfo
641                .get_harness()
642                .read_polymorphic_data_as_send_sync_any(context, &typeinfo)?;
643            context.dec_depth();
644            let arc: Arc<dyn Any + Send + Sync> = Arc::from(boxed);
645            context.ref_reader.store_arc_ref_at(ref_id, arc.clone());
646            Ok(arc)
647        }
648    }
649}