rkyv_test/de/deserializers/
alloc.rs

1//! Adapters wrap deserializers and add support for deserializer traits.
2
3use crate::{
4    de::{SharedDeserializeRegistry, SharedPointer},
5    Fallible,
6};
7#[cfg(not(feature = "std"))]
8use alloc::boxed::Box;
9use core::fmt;
10#[cfg(not(feature = "std"))]
11use hashbrown::hash_map;
12#[cfg(feature = "std")]
13use std::collections::hash_map;
14
15/// An error that can occur while deserializing shared pointers.
16#[derive(Debug)]
17pub enum SharedDeserializeMapError {
18    /// A shared pointer was added multiple times
19    DuplicateSharedPointer(*const u8),
20}
21
22// SAFETY: SharedDeserializeMapError is safe to send to another thread
23// This trait is not automatically implemented because the enum contains a pointer
24unsafe impl Send for SharedDeserializeMapError {}
25
26// SAFETY: SharedDeserializeMapError is safe to share between threads
27// This trait is not automatically implemented because the enum contains a pointer
28unsafe impl Sync for SharedDeserializeMapError {}
29
30impl fmt::Display for SharedDeserializeMapError {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        match self {
33            Self::DuplicateSharedPointer(p) => write!(f, "duplicate shared pointer: {:p}", p),
34        }
35    }
36}
37
38#[cfg(feature = "std")]
39const _: () = {
40    use std::error::Error;
41
42    impl Error for SharedDeserializeMapError {}
43};
44
45/// An adapter that adds shared deserialization support to a deserializer.
46pub struct SharedDeserializeMap {
47    shared_pointers: hash_map::HashMap<*const u8, Box<dyn SharedPointer>>,
48}
49
50impl SharedDeserializeMap {
51    /// Wraps the given deserializer and adds shared memory support.
52    #[inline]
53    pub fn new() -> Self {
54        Self {
55            shared_pointers: hash_map::HashMap::new(),
56        }
57    }
58}
59
60impl fmt::Debug for SharedDeserializeMap {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        f.debug_map()
63            .entries(
64                self.shared_pointers
65                    .iter()
66                    .map(|(s, p)| (s, &**p as *const _)),
67            )
68            .finish()
69    }
70}
71
72impl Default for SharedDeserializeMap {
73    #[inline]
74    fn default() -> Self {
75        Self::new()
76    }
77}
78
79impl Fallible for SharedDeserializeMap {
80    type Error = SharedDeserializeMapError;
81}
82
83impl SharedDeserializeRegistry for SharedDeserializeMap {
84    fn get_shared_ptr(&mut self, ptr: *const u8) -> Option<&dyn SharedPointer> {
85        self.shared_pointers.get(&ptr).map(|p| p.as_ref())
86    }
87
88    fn add_shared_ptr(
89        &mut self,
90        ptr: *const u8,
91        shared: Box<dyn SharedPointer>,
92    ) -> Result<(), Self::Error> {
93        match self.shared_pointers.entry(ptr) {
94            hash_map::Entry::Occupied(_) => {
95                Err(SharedDeserializeMapError::DuplicateSharedPointer(ptr))
96            }
97            hash_map::Entry::Vacant(e) => {
98                e.insert(shared);
99                Ok(())
100            }
101        }
102    }
103}