flatty_base/
wrap.rs

1#[cfg(feature = "alloc")]
2use crate::utils::alloc::AlignedBytes;
3use crate::{
4    emplacer::Emplacer,
5    error::Error,
6    traits::{Flat, FlatDefault},
7};
8#[cfg(feature = "alloc")]
9use alloc::{boxed::Box, ffi::CString, rc::Rc, string::String, sync::Arc, vec::Vec};
10use core::{
11    cell::{Ref, RefMut},
12    marker::PhantomData,
13    mem::ManuallyDrop,
14    ops::{Deref, DerefMut},
15    pin::Pin,
16};
17use stavec::{
18    traits::{Container, Length},
19    GenericVec,
20};
21
22/// Extra guarantees for [`Deref`] and [`DerefMut`].
23///
24/// # Safety
25///
26/// Types implementing this trait must guarantee that data referred by `deref` and `deref_mut` (and reference metadata)
27/// will not change internally between these calls (excluding interior mutability).
28pub unsafe trait TrustedDeref: Deref {}
29
30/// Wrapper for smart pointer to byte slice that maps it to flat type.
31pub struct FlatWrap<F: Flat + ?Sized, P: TrustedDeref<Target = [u8]>> {
32    pointer: P,
33    _ghost: PhantomData<F>,
34}
35
36impl<F: Flat + ?Sized, P: TrustedDeref<Target = [u8]>> FlatWrap<F, P> {
37    pub unsafe fn from_wrapped_bytes_unchecked(pointer: P) -> Self {
38        Self {
39            pointer,
40            _ghost: PhantomData,
41        }
42    }
43    pub fn into_inner(self) -> P {
44        self.pointer
45    }
46
47    pub fn from_wrapped_bytes(pointer: P) -> Result<Self, Error> {
48        F::validate(&pointer)?;
49        Ok(unsafe { Self::from_wrapped_bytes_unchecked(pointer) })
50    }
51
52    pub fn new_in_place(mut pointer: P, emplacer: impl Emplacer<F>) -> Result<Self, Error>
53    where
54        P: DerefMut,
55    {
56        F::new_in_place(&mut pointer, emplacer)?;
57        Ok(unsafe { Self::from_wrapped_bytes_unchecked(pointer) })
58    }
59    pub fn default_in_place(pointer: P) -> Result<Self, Error>
60    where
61        P: DerefMut,
62        F: FlatDefault,
63    {
64        Self::new_in_place(pointer, F::default_emplacer())
65    }
66}
67
68impl<F: Flat + ?Sized, P: TrustedDeref<Target = [u8]>> Deref for FlatWrap<F, P> {
69    type Target = F;
70    fn deref(&self) -> &Self::Target {
71        unsafe { F::from_bytes_unchecked(&self.pointer) }
72    }
73}
74impl<F: Flat + ?Sized, P: TrustedDeref<Target = [u8]> + DerefMut> DerefMut for FlatWrap<F, P> {
75    fn deref_mut(&mut self) -> &mut Self::Target {
76        unsafe { F::from_mut_bytes_unchecked(&mut self.pointer) }
77    }
78}
79
80unsafe impl<'a, T: ?Sized> TrustedDeref for &'a T {}
81unsafe impl<'a, T: ?Sized> TrustedDeref for &'a mut T {}
82
83unsafe impl<P: Deref> TrustedDeref for Pin<P> {}
84unsafe impl<T: ?Sized> TrustedDeref for ManuallyDrop<T> {}
85unsafe impl<'a, T: ?Sized> TrustedDeref for Ref<'a, T> {}
86unsafe impl<'a, T: ?Sized> TrustedDeref for RefMut<'a, T> {}
87#[cfg(feature = "alloc")]
88unsafe impl<T: ?Sized> TrustedDeref for Box<T> {}
89#[cfg(feature = "alloc")]
90unsafe impl<T: ?Sized> TrustedDeref for Rc<T> {}
91#[cfg(feature = "alloc")]
92unsafe impl<T: ?Sized> TrustedDeref for Arc<T> {}
93
94#[cfg(feature = "alloc")]
95unsafe impl<T> TrustedDeref for Vec<T> {}
96#[cfg(feature = "alloc")]
97unsafe impl TrustedDeref for String {}
98#[cfg(feature = "alloc")]
99unsafe impl TrustedDeref for CString {}
100
101unsafe impl<C: Container + ?Sized, L: Length> TrustedDeref for GenericVec<C, L> {}
102#[cfg(feature = "alloc")]
103unsafe impl TrustedDeref for AlignedBytes {}
104
105#[cfg(all(test, feature = "std"))]
106mod tests {
107    use super::*;
108    use crate::{utils::alloc::AlignedBytes, vec::FlatVec};
109
110    #[test]
111    fn wrapped_vec() {
112        let mut wrap = FlatWrap::<FlatVec<u8, u16>, _>::default_in_place(AlignedBytes::new(2 + 4, 2)).unwrap();
113
114        assert_eq!(wrap.capacity(), 4);
115        assert_eq!(wrap.len(), 0);
116        assert_eq!(wrap.remaining(), 4);
117
118        assert_eq!(wrap.extend_from_slice(&[1, 2]), 2);
119        assert_eq!(wrap.len(), 2);
120        assert_eq!(wrap.remaining(), 2);
121        assert_eq!(wrap.as_slice(), [1, 2].as_slice());
122
123        assert_eq!(wrap.extend_from_slice(&[3, 4, 5]), 2);
124        assert_eq!(wrap.len(), 4);
125        assert_eq!(wrap.remaining(), 0);
126        assert_eq!(wrap.as_slice(), [1, 2, 3, 4].as_slice());
127
128        let bytes = wrap.into_inner();
129        assert_eq!(bytes.deref(), [4, 0, 1, 2, 3, 4].as_slice())
130    }
131}