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::error::Error;
20use crate::resolver::{RefFlag, RefMode, TypeInfo};
21use crate::serializer::Serializer;
22use crate::type_id::TypeId;
23use std::any::Any;
24use std::rc::Rc;
25use std::sync::Arc;
26
27#[inline]
28fn is_erased_any_container_type(type_id: TypeId) -> bool {
29    matches!(
30        type_id,
31        TypeId::LIST
32            | TypeId::SET
33            | TypeId::MAP
34            | TypeId::BINARY
35            | TypeId::ARRAY
36            | TypeId::BOOL_ARRAY
37            | TypeId::INT8_ARRAY
38            | TypeId::INT16_ARRAY
39            | TypeId::INT32_ARRAY
40            | TypeId::INT64_ARRAY
41            | TypeId::UINT8_ARRAY
42            | TypeId::UINT16_ARRAY
43            | TypeId::UINT32_ARRAY
44            | TypeId::UINT64_ARRAY
45            | TypeId::FLOAT8_ARRAY
46            | TypeId::FLOAT16_ARRAY
47            | TypeId::BFLOAT16_ARRAY
48            | TypeId::FLOAT32_ARRAY
49            | TypeId::FLOAT64_ARRAY
50            | TypeId::U128_ARRAY
51            | TypeId::INT128_ARRAY
52            | TypeId::USIZE_ARRAY
53            | TypeId::ISIZE_ARRAY
54    )
55}
56
57#[cold]
58#[inline(never)]
59fn unsupported_erased_any_container() -> Error {
60    Error::type_error(
61        "built-in list, set, map, binary, and primitive-array values cannot be top-level erased \
62         Any or application-trait payloads; register an exact manual EXT serializer for the whole \
63         target or wrap it in a registered structural type",
64    )
65}
66
67#[cold]
68#[inline(never)]
69fn erased_any_type_info_error(err: Error) -> Error {
70    Error::type_error(format!(
71        "{err}. Erased Any payloads require a registered concrete target"
72    ))
73}
74
75#[cold]
76#[inline(never)]
77fn missing_dynamic_target() -> Error {
78    Error::type_error("dynamic target metadata has no checked local serializer registration")
79}
80
81#[cold]
82#[inline(never)]
83fn mismatched_dynamic_target(expected: std::any::TypeId, actual: std::any::TypeId) -> Error {
84    Error::type_error(format!(
85        "dynamic target metadata expected TypeId {:?}, got {:?}",
86        expected, actual,
87    ))
88}
89
90#[cold]
91#[inline(never)]
92fn missing_any_ref(owner: &'static str, ref_id: u32) -> Error {
93    Error::invalid_data(format!("{owner} reference {ref_id} not found"))
94}
95
96#[cold]
97#[inline(never)]
98fn box_any_null() -> Error {
99    Error::invalid_ref("Box<dyn Any> cannot be null")
100}
101
102#[cold]
103#[inline(never)]
104fn box_any_metadata() -> Error {
105    Error::invalid_data("Box<dyn Any> requires concrete type metadata")
106}
107
108#[cold]
109#[inline(never)]
110fn rc_any_null() -> Error {
111    Error::invalid_ref("Rc<dyn Any> cannot be null")
112}
113
114#[cold]
115#[inline(never)]
116fn rc_any_metadata() -> Error {
117    Error::invalid_data("Rc<dyn Any> requires concrete type metadata")
118}
119
120#[cold]
121#[inline(never)]
122fn arc_any_null() -> Error {
123    Error::invalid_ref("Arc<dyn Any + Send + Sync> cannot be null")
124}
125
126#[cold]
127#[inline(never)]
128fn arc_any_metadata() -> Error {
129    Error::invalid_data("Arc<dyn Any + Send + Sync> requires concrete type metadata")
130}
131
132#[doc(hidden)]
133#[inline]
134pub fn check_erased_target_type(type_info: &TypeInfo) -> Result<(), Error> {
135    if is_erased_any_container_type(type_info.get_type_id()) {
136        return Err(unsupported_erased_any_container());
137    }
138    Ok(())
139}
140
141#[inline(always)]
142fn check_local_target(type_info: &TypeInfo) -> Result<(), Error> {
143    type_info
144        .get_harness()
145        .target_type_id()
146        .ok_or_else(missing_dynamic_target)
147        .map(|_| ())
148}
149
150#[inline(always)]
151fn check_resolved_target(
152    target_type_id: std::any::TypeId,
153    type_info: &TypeInfo,
154) -> Result<(), Error> {
155    check_erased_target_type(type_info)?;
156    let resolved_target_type_id = type_info
157        .get_harness()
158        .target_type_id()
159        .ok_or_else(missing_dynamic_target)?;
160    if resolved_target_type_id != target_type_id {
161        return Err(mismatched_dynamic_target(
162            resolved_target_type_id,
163            target_type_id,
164        ));
165    }
166    Ok(())
167}
168
169#[inline]
170fn get_erased_any_type_info(
171    context: &WriteContext,
172    target_type_id: &std::any::TypeId,
173) -> Result<Rc<TypeInfo>, Error> {
174    let type_info = context
175        .get_target_type_info(target_type_id)
176        .map_err(erased_any_type_info_error)?;
177    check_erased_target_type(&type_info)?;
178    Ok(type_info)
179}
180
181#[inline]
182fn write_erased_any_type_info(
183    context: &mut WriteContext,
184    target_type_id: std::any::TypeId,
185) -> Result<Rc<TypeInfo>, Error> {
186    let type_info = context
187        .get_target_type_info(&target_type_id)
188        .map_err(erased_any_type_info_error)?;
189    check_erased_target_type(&type_info)?;
190    context.write_resolved_type_info(TypeId::UNKNOWN as u32, type_info)
191}
192
193#[inline(always)]
194fn write_any_body(value: &dyn Any, context: &mut WriteContext) -> Result<(), Error> {
195    let type_info = get_erased_any_type_info(context, &value.type_id())?;
196    write_resolved_any_body(value, context, &type_info)
197}
198
199#[inline(always)]
200fn write_resolved_any_body(
201    value: &dyn Any,
202    context: &mut WriteContext,
203    type_info: &Rc<TypeInfo>,
204) -> Result<(), Error> {
205    check_resolved_target(value.type_id(), type_info)?;
206    write_any_harness(value, context, type_info)
207}
208
209#[inline(always)]
210fn write_any_harness(
211    value: &dyn Any,
212    context: &mut WriteContext,
213    type_info: &Rc<TypeInfo>,
214) -> Result<(), Error> {
215    type_info.get_harness().write_data(value, context)
216}
217
218/// Reads a non-null `Box<dyn Any>` with concrete type metadata.
219pub fn deserialize_any_box(context: &mut ReadContext) -> Result<Box<dyn Any>, Error> {
220    read_box_any(context, RefMode::NullOnly, true, None)
221}
222
223impl Serializer for Box<dyn Any> {
224    type Target = Self;
225    #[inline(always)]
226    fn write_data(value: &Self, context: &mut WriteContext) -> Result<(), Error> {
227        write_any_body(value.as_ref(), context)
228    }
229
230    #[cold]
231    #[inline(never)]
232    fn read_data(_: &mut ReadContext) -> Result<Self, Error> {
233        Err(Error::not_allowed(
234            "Box<dyn Any> requires concrete type metadata",
235        ))
236    }
237
238    #[inline(always)]
239    fn write_type_info_value(
240        context: &mut WriteContext,
241        target_type_id: std::any::TypeId,
242    ) -> Result<Rc<TypeInfo>, Error> {
243        write_erased_any_type_info(context, target_type_id)
244    }
245
246    #[inline(always)]
247    fn write_with_type_info(
248        value: &Self,
249        context: &mut WriteContext,
250        ref_mode: RefMode,
251        type_info: &Rc<TypeInfo>,
252    ) -> Result<(), Error> {
253        write_box_any_resolved(value.as_ref(), context, ref_mode, type_info)
254    }
255
256    #[inline(always)]
257    fn write(
258        value: &Self,
259        context: &mut WriteContext,
260        ref_mode: RefMode,
261        write_type_info: bool,
262    ) -> Result<(), Error> {
263        write_box_any(value.as_ref(), context, ref_mode, write_type_info)
264    }
265
266    #[inline(always)]
267    fn read(
268        context: &mut ReadContext,
269        ref_mode: RefMode,
270        read_type_info: bool,
271    ) -> Result<Self, Error> {
272        read_box_any(context, ref_mode, read_type_info, None)
273    }
274
275    #[inline(always)]
276    fn read_with_type_info(
277        context: &mut ReadContext,
278        ref_mode: RefMode,
279        type_info: &Rc<TypeInfo>,
280    ) -> Result<Self, Error> {
281        read_box_any(context, ref_mode, false, Some(type_info))
282    }
283
284    #[inline(always)]
285    fn write_type_info(_: &mut WriteContext) -> Result<(), Error> {
286        Ok(())
287    }
288
289    #[inline(always)]
290    fn read_type_info(_: &mut ReadContext) -> Result<(), Error> {
291        Ok(())
292    }
293
294    #[inline(always)]
295    fn static_type_id() -> TypeId {
296        TypeId::UNKNOWN
297    }
298
299    const IS_POLYMORPHIC: bool = true;
300
301    const IS_WRAPPER: bool = true;
302
303    #[inline(always)]
304    fn dynamic_type_id(value: &Self) -> Result<Option<std::any::TypeId>, Error> {
305        Ok(Some(value.as_ref().type_id()))
306    }
307}
308
309pub fn write_box_any(
310    value: &dyn Any,
311    context: &mut WriteContext,
312    ref_mode: RefMode,
313    write_type_info: bool,
314) -> Result<(), Error> {
315    let target_type_id = value.type_id();
316    let type_info = get_erased_any_type_info(context, &target_type_id)?;
317    if ref_mode != RefMode::None {
318        context.writer.write_i8(RefFlag::NotNullValue as i8);
319    }
320    let type_info = if write_type_info {
321        context.write_resolved_type_info(TypeId::UNKNOWN as u32, type_info)?
322    } else {
323        type_info
324    };
325    write_any_harness(value, context, &type_info)
326}
327
328#[inline(always)]
329fn write_box_any_resolved(
330    value: &dyn Any,
331    context: &mut WriteContext,
332    ref_mode: RefMode,
333    type_info: &Rc<TypeInfo>,
334) -> Result<(), Error> {
335    check_resolved_target(value.type_id(), type_info)?;
336    if ref_mode != RefMode::None {
337        context.writer.write_i8(RefFlag::NotNullValue as i8);
338    }
339    write_any_harness(value, context, type_info)
340}
341
342pub fn read_box_any(
343    context: &mut ReadContext,
344    ref_mode: RefMode,
345    read_type_info: bool,
346    type_info: Option<&Rc<TypeInfo>>,
347) -> Result<Box<dyn Any>, Error> {
348    context.inc_depth()?;
349    let result = (|| {
350        let ref_flag = if ref_mode != RefMode::None {
351            context.reader.read_i8()?
352        } else {
353            RefFlag::NotNullValue as i8
354        };
355        if ref_flag != RefFlag::NotNullValue as i8 {
356            return Err(box_any_null());
357        }
358        let owned_type_info;
359        let type_info = if let Some(type_info) = type_info {
360            type_info
361        } else if read_type_info {
362            owned_type_info = context.read_any_type_info()?;
363            &owned_type_info
364        } else {
365            return Err(box_any_metadata());
366        };
367        check_local_target(type_info)?;
368        check_erased_target_type(type_info)?;
369        type_info.get_harness().read_box_any(context, type_info)
370    })();
371    context.dec_depth();
372    result
373}
374
375impl Serializer for Rc<dyn Any> {
376    type Target = Self;
377    #[inline(always)]
378    fn write_data(value: &Self, context: &mut WriteContext) -> Result<(), Error> {
379        write_any_body(value.as_ref(), context)
380    }
381
382    #[cold]
383    #[inline(never)]
384    fn read_data(_: &mut ReadContext) -> Result<Self, Error> {
385        Err(Error::not_allowed(
386            "Rc<dyn Any> requires concrete type metadata",
387        ))
388    }
389
390    #[inline(always)]
391    fn write_type_info_value(
392        context: &mut WriteContext,
393        target_type_id: std::any::TypeId,
394    ) -> Result<Rc<TypeInfo>, Error> {
395        write_erased_any_type_info(context, target_type_id)
396    }
397
398    #[inline(always)]
399    fn write_with_type_info(
400        value: &Self,
401        context: &mut WriteContext,
402        ref_mode: RefMode,
403        type_info: &Rc<TypeInfo>,
404    ) -> Result<(), Error> {
405        write_rc_any_resolved(value, context, ref_mode, type_info)
406    }
407
408    #[inline(always)]
409    fn write(
410        value: &Self,
411        context: &mut WriteContext,
412        ref_mode: RefMode,
413        write_type_info: bool,
414    ) -> Result<(), Error> {
415        if ref_mode != RefMode::None
416            && context
417                .ref_writer
418                .try_write_rc_ref(&mut context.writer, value)
419        {
420            return Ok(());
421        }
422        let target_type_id = value.as_ref().type_id();
423        let type_info = get_erased_any_type_info(context, &target_type_id)?;
424        let type_info = if write_type_info {
425            context.write_resolved_type_info(TypeId::UNKNOWN as u32, type_info)?
426        } else {
427            type_info
428        };
429        write_any_harness(value.as_ref(), context, &type_info)
430    }
431
432    #[inline(always)]
433    fn read(
434        context: &mut ReadContext,
435        ref_mode: RefMode,
436        read_type_info: bool,
437    ) -> Result<Self, Error> {
438        read_rc_any(context, ref_mode, read_type_info, None)
439    }
440
441    #[inline(always)]
442    fn read_with_type_info(
443        context: &mut ReadContext,
444        ref_mode: RefMode,
445        type_info: &Rc<TypeInfo>,
446    ) -> Result<Self, Error> {
447        read_rc_any(context, ref_mode, false, Some(type_info))
448    }
449
450    #[inline(always)]
451    fn write_type_info(_: &mut WriteContext) -> Result<(), Error> {
452        Ok(())
453    }
454
455    #[inline(always)]
456    fn read_type_info(_: &mut ReadContext) -> Result<(), Error> {
457        Ok(())
458    }
459
460    #[inline(always)]
461    fn static_type_id() -> TypeId {
462        TypeId::UNKNOWN
463    }
464
465    const IS_SHARED_REF: bool = true;
466
467    const IS_POLYMORPHIC: bool = true;
468
469    const IS_WRAPPER: bool = true;
470
471    #[inline(always)]
472    fn dynamic_type_id(value: &Self) -> Result<Option<std::any::TypeId>, Error> {
473        Ok(Some(value.as_ref().type_id()))
474    }
475}
476
477#[inline(always)]
478fn write_rc_any_resolved(
479    value: &Rc<dyn Any>,
480    context: &mut WriteContext,
481    ref_mode: RefMode,
482    type_info: &Rc<TypeInfo>,
483) -> Result<(), Error> {
484    let any = value.as_ref();
485    check_resolved_target(any.type_id(), type_info)?;
486    if ref_mode != RefMode::None
487        && context
488            .ref_writer
489            .try_write_rc_ref(&mut context.writer, value)
490    {
491        return Ok(());
492    }
493    write_any_harness(any, context, type_info)
494}
495
496pub fn read_rc_any(
497    context: &mut ReadContext,
498    ref_mode: RefMode,
499    read_type_info: bool,
500    type_info: Option<&Rc<TypeInfo>>,
501) -> Result<Rc<dyn Any>, Error> {
502    let ref_flag = if ref_mode != RefMode::None {
503        context.ref_reader.read_ref_flag(&mut context.reader)?
504    } else {
505        RefFlag::NotNullValue
506    };
507    match ref_flag {
508        RefFlag::Null => Err(rc_any_null()),
509        RefFlag::Ref => {
510            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
511            context
512                .ref_reader
513                .get_rc_ref::<dyn Any>(ref_id)
514                .ok_or_else(|| missing_any_ref("Rc<dyn Any>", ref_id))
515        }
516        RefFlag::NotNullValue => read_new_rc_any(context, read_type_info, type_info),
517        RefFlag::RefValue => {
518            let ref_id = context.ref_reader.reserve_ref_id();
519            let value = read_new_rc_any(context, read_type_info, type_info)?;
520            context.ref_reader.store_rc_ref_at(ref_id, value.clone());
521            Ok(value)
522        }
523    }
524}
525
526fn read_new_rc_any(
527    context: &mut ReadContext,
528    read_type_info: bool,
529    type_info: Option<&Rc<TypeInfo>>,
530) -> Result<Rc<dyn Any>, Error> {
531    context.inc_depth()?;
532    let result = (|| {
533        let owned_type_info;
534        let type_info = if read_type_info {
535            owned_type_info = context.read_any_type_info()?;
536            &owned_type_info
537        } else {
538            type_info.ok_or_else(rc_any_metadata)?
539        };
540        check_local_target(type_info)?;
541        check_erased_target_type(type_info)?;
542        type_info.get_harness().read_rc_any(context, type_info)
543    })();
544    context.dec_depth();
545    result
546}
547
548impl Serializer for Arc<dyn Any + Send + Sync> {
549    type Target = Self;
550    #[inline(always)]
551    fn write_data(value: &Self, context: &mut WriteContext) -> Result<(), Error> {
552        write_any_body(value.as_ref(), context)
553    }
554
555    #[cold]
556    #[inline(never)]
557    fn read_data(_: &mut ReadContext) -> Result<Self, Error> {
558        Err(Error::not_allowed(
559            "Arc<dyn Any + Send + Sync> requires concrete type metadata",
560        ))
561    }
562
563    #[inline(always)]
564    fn write_type_info_value(
565        context: &mut WriteContext,
566        target_type_id: std::any::TypeId,
567    ) -> Result<Rc<TypeInfo>, Error> {
568        write_erased_any_type_info(context, target_type_id)
569    }
570
571    #[inline(always)]
572    fn write_with_type_info(
573        value: &Self,
574        context: &mut WriteContext,
575        ref_mode: RefMode,
576        type_info: &Rc<TypeInfo>,
577    ) -> Result<(), Error> {
578        write_arc_any_resolved(value, context, ref_mode, type_info)
579    }
580
581    #[inline(always)]
582    fn write(
583        value: &Self,
584        context: &mut WriteContext,
585        ref_mode: RefMode,
586        write_type_info: bool,
587    ) -> Result<(), Error> {
588        if ref_mode != RefMode::None
589            && context
590                .ref_writer
591                .try_write_arc_ref(&mut context.writer, value)
592        {
593            return Ok(());
594        }
595        let target_type_id = value.as_ref().type_id();
596        let type_info = get_erased_any_type_info(context, &target_type_id)?;
597        let type_info = if write_type_info {
598            context.write_resolved_type_info(TypeId::UNKNOWN as u32, type_info)?
599        } else {
600            type_info
601        };
602        write_any_harness(value.as_ref(), context, &type_info)
603    }
604
605    #[inline(always)]
606    fn read(
607        context: &mut ReadContext,
608        ref_mode: RefMode,
609        read_type_info: bool,
610    ) -> Result<Self, Error> {
611        read_arc_any(context, ref_mode, read_type_info, None)
612    }
613
614    #[inline(always)]
615    fn read_with_type_info(
616        context: &mut ReadContext,
617        ref_mode: RefMode,
618        type_info: &Rc<TypeInfo>,
619    ) -> Result<Self, Error> {
620        read_arc_any(context, ref_mode, false, Some(type_info))
621    }
622
623    #[inline(always)]
624    fn write_type_info(_: &mut WriteContext) -> Result<(), Error> {
625        Ok(())
626    }
627
628    #[inline(always)]
629    fn read_type_info(_: &mut ReadContext) -> Result<(), Error> {
630        Ok(())
631    }
632
633    #[inline(always)]
634    fn static_type_id() -> TypeId {
635        TypeId::UNKNOWN
636    }
637
638    const IS_SHARED_REF: bool = true;
639
640    const IS_POLYMORPHIC: bool = true;
641
642    const IS_WRAPPER: bool = true;
643
644    #[inline(always)]
645    fn dynamic_type_id(value: &Self) -> Result<Option<std::any::TypeId>, Error> {
646        Ok(Some(value.as_ref().type_id()))
647    }
648}
649
650#[inline(always)]
651fn write_arc_any_resolved(
652    value: &Arc<dyn Any + Send + Sync>,
653    context: &mut WriteContext,
654    ref_mode: RefMode,
655    type_info: &Rc<TypeInfo>,
656) -> Result<(), Error> {
657    let any = value.as_ref();
658    check_resolved_target(any.type_id(), type_info)?;
659    if ref_mode != RefMode::None
660        && context
661            .ref_writer
662            .try_write_arc_ref(&mut context.writer, value)
663    {
664        return Ok(());
665    }
666    write_any_harness(any, context, type_info)
667}
668
669pub fn read_arc_any(
670    context: &mut ReadContext,
671    ref_mode: RefMode,
672    read_type_info: bool,
673    type_info: Option<&Rc<TypeInfo>>,
674) -> Result<Arc<dyn Any + Send + Sync>, Error> {
675    let ref_flag = if ref_mode != RefMode::None {
676        context.ref_reader.read_ref_flag(&mut context.reader)?
677    } else {
678        RefFlag::NotNullValue
679    };
680    match ref_flag {
681        RefFlag::Null => Err(arc_any_null()),
682        RefFlag::Ref => {
683            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
684            context
685                .ref_reader
686                .get_arc_ref::<dyn Any + Send + Sync>(ref_id)
687                .ok_or_else(|| missing_any_ref("Arc<dyn Any + Send + Sync>", ref_id))
688        }
689        RefFlag::NotNullValue => read_new_arc_any(context, read_type_info, type_info),
690        RefFlag::RefValue => {
691            let ref_id = context.ref_reader.reserve_ref_id();
692            let value = read_new_arc_any(context, read_type_info, type_info)?;
693            context.ref_reader.store_arc_ref_at(ref_id, value.clone());
694            Ok(value)
695        }
696    }
697}
698
699fn read_new_arc_any(
700    context: &mut ReadContext,
701    read_type_info: bool,
702    type_info: Option<&Rc<TypeInfo>>,
703) -> Result<Arc<dyn Any + Send + Sync>, Error> {
704    context.inc_depth()?;
705    let result = (|| {
706        let owned_type_info;
707        let type_info = if read_type_info {
708            owned_type_info = context.read_any_type_info()?;
709            &owned_type_info
710        } else {
711            type_info.ok_or_else(arc_any_metadata)?
712        };
713        check_local_target(type_info)?;
714        check_erased_target_type(type_info)?;
715        type_info.get_harness().read_arc_any(context, type_info)
716    })();
717    context.dec_depth();
718    result
719}