rkyv/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    /// Wraps the given deserializer and adds shared memory support, with initial capacity.
60    #[inline]
61    pub fn with_capacity(capacity: usize) -> Self {
62        Self {
63            shared_pointers: hash_map::HashMap::with_capacity(capacity),
64        }
65    }
66}
67
68impl fmt::Debug for SharedDeserializeMap {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        f.debug_map()
71            .entries(
72                self.shared_pointers
73                    .iter()
74                    .map(|(s, p)| (s, &**p as *const _)),
75            )
76            .finish()
77    }
78}
79
80impl Default for SharedDeserializeMap {
81    #[inline]
82    fn default() -> Self {
83        Self::new()
84    }
85}
86
87impl Fallible for SharedDeserializeMap {
88    type Error = SharedDeserializeMapError;
89}
90
91impl SharedDeserializeRegistry for SharedDeserializeMap {
92    fn get_shared_ptr(&mut self, ptr: *const u8) -> Option<&dyn SharedPointer> {
93        self.shared_pointers.get(&ptr).map(|p| p.as_ref())
94    }
95
96    fn add_shared_ptr(
97        &mut self,
98        ptr: *const u8,
99        shared: Box<dyn SharedPointer>,
100    ) -> Result<(), Self::Error> {
101        match self.shared_pointers.entry(ptr) {
102            hash_map::Entry::Occupied(_) => {
103                Err(SharedDeserializeMapError::DuplicateSharedPointer(ptr))
104            }
105            hash_map::Entry::Vacant(e) => {
106                e.insert(shared);
107                Ok(())
108            }
109        }
110    }
111}