facet_reflect/poke/
map.rs

1use crate::PokeValueUninit;
2use facet_core::{MapDef, MapVTable, Opaque, OpaqueConst, OpaqueUninit, Shape};
3
4/// Allows initializing an uninitialized map
5pub struct PokeMapUninit<'mem> {
6    data: OpaqueUninit<'mem>,
7    shape: &'static Shape,
8    def: MapDef,
9}
10
11impl<'mem> PokeMapUninit<'mem> {
12    #[inline(always)]
13    /// Coerce back into a `PokeValue`
14    pub fn into_value(self) -> PokeValueUninit<'mem> {
15        unsafe { PokeValueUninit::new(self.data, self.shape) }
16    }
17
18    #[inline(always)]
19    /// Shape getter
20    pub fn shape(&self) -> &'static Shape {
21        self.shape
22    }
23    /// Creates a new uninitialized map write-proxy
24    ///
25    /// # Safety
26    ///
27    /// The data buffer must match the size and alignment of the shape.
28    pub(crate) unsafe fn new(data: OpaqueUninit<'mem>, shape: &'static Shape, def: MapDef) -> Self {
29        Self { data, shape, def }
30    }
31
32    /// Initializes the map with an optional size hint
33    pub fn init(self, size_hint: Option<usize>) -> Result<PokeMap<'mem>, OpaqueUninit<'mem>> {
34        let res = if let Some(capacity) = size_hint {
35            let init_in_place_with_capacity = self.def.vtable.init_in_place_with_capacity_fn;
36            unsafe { init_in_place_with_capacity(self.data, capacity) }
37        } else {
38            let pv = unsafe { PokeValueUninit::new(self.data, self.shape) };
39            pv.default_in_place().map_err(|_| ())
40        };
41        let data = res.map_err(|_| self.data)?;
42        Ok(unsafe { PokeMap::new(data, self.shape, self.def) })
43    }
44}
45
46/// Allows poking a map (inserting, etc.)
47pub struct PokeMap<'mem> {
48    data: Opaque<'mem>,
49    #[allow(dead_code)]
50    shape: &'static Shape,
51    def: MapDef,
52}
53
54impl<'mem> PokeMap<'mem> {
55    /// Creates a value-proxy for a map
56    ///
57    /// # Safety
58    ///
59    /// The data buffer must match the size and alignment of the shape.
60    #[inline]
61    pub(crate) unsafe fn new(data: Opaque<'mem>, shape: &'static Shape, def: MapDef) -> Self {
62        Self { data, shape, def }
63    }
64
65    /// Get the shape of the map
66    #[inline(always)]
67    pub fn shape(&self) -> &'static Shape {
68        self.shape
69    }
70
71    /// Gets the vtable for the map
72    #[inline(always)]
73    pub fn map_vtable(&self) -> &'static MapVTable {
74        self.def.vtable
75    }
76
77    /// Inserts a key-value pair into the map
78    ///
79    /// # Safety
80    ///
81    /// `key` and `value` are moved out of (with [`core::ptr::read`]) — they should be deallocated
82    /// afterwards but NOT dropped.
83    #[inline]
84    pub unsafe fn insert(&mut self, key: Opaque<'_>, value: Opaque<'_>) {
85        unsafe { (self.map_vtable().insert_fn)(self.data, key, value) }
86    }
87
88    /// Gets the number of entries in the map
89    #[inline]
90    pub fn len(&self) -> usize {
91        unsafe { (self.map_vtable().len_fn)(self.data.as_const()) }
92    }
93
94    /// Checks if the map contains no entries
95    #[inline]
96    pub fn is_empty(&self) -> bool {
97        self.len() == 0
98    }
99
100    /// Checks if the map contains a key
101    #[inline]
102    pub fn contains_key(&self, key: OpaqueConst<'_>) -> bool {
103        unsafe { (self.map_vtable().contains_key_fn)(self.data.as_const(), key) }
104    }
105
106    /// Gets a pointer to the value for a given key
107    ///
108    /// Returns `None` if the key is not found.
109    #[inline]
110    pub fn get_value_ptr<'key>(&self, key: OpaqueConst<'key>) -> Option<OpaqueConst<'mem>> {
111        unsafe { (self.map_vtable().get_value_ptr_fn)(self.data.as_const(), key) }
112    }
113
114    /// Takes ownership of this `PokeList` and returns the underlying data.
115    pub fn build_in_place(self) -> Opaque<'mem> {
116        self.data
117    }
118
119    /// Returns a reference to the `MapDef` of this `PokeMap`.
120    #[inline]
121    pub fn def(&self) -> &MapDef {
122        &self.def
123    }
124}