1use 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
218pub 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}