devela/data/dst/
buffer.rs

1// devela::data::dst
2
3use crate::{Array, ConstDefault, Deref, DerefMut, MaybeUninit, MemPod};
4
5#[doc = crate::TAG_DATA_STRUCTURE!()]
6/// Represents the backing buffer for storing dynamically sized types.
7///
8/// # Safety
9/// Must conform to the following rules:
10/// - The `as_ref`/`as_mut` methods must return pointers to the same data.
11/// - The pointer returned by `as_mut` must be stable until either a call to
12///   `extend` or the value is moved (i.e. `let a = foo.as_mut().as_ptr();
13///   let b = foo.as_mut().as_ptr(); assert!(a == b)` always holds).
14/// - `extend` must not change any contained data
15///   (but may extend with unspecified values).
16pub unsafe trait DstBuf {
17    /// Inner type of the buffer
18    type Inner: MemPod;
19
20    /// Get the buffer slice as shared reference.
21    fn as_ref(&self) -> &[MaybeUninit<Self::Inner>];
22
23    /// Get the buffer slice as an exclusive reference.
24    fn as_mut(&mut self) -> &mut [MaybeUninit<Self::Inner>];
25
26    /// Extend the buffer (fallible).
27    fn extend(&mut self, len: usize) -> Result<(), ()>;
28
29    /// Convert a byte count to a word count (rounding up).
30    fn round_to_words(bytes: usize) -> usize {
31        super::round_to_words::<Self::Inner>(bytes)
32    }
33}
34
35// impl for an exclusive reference
36#[rustfmt::skip]
37unsafe impl<T, U> DstBuf for &mut T where U: MemPod, T: DstBuf<Inner = U> {
38    type Inner = T::Inner;
39
40    fn as_ref(&self) -> &[MaybeUninit<Self::Inner>] {
41        (**self).as_ref()
42    }
43    fn as_mut(&mut self) -> &mut [MaybeUninit<Self::Inner>] {
44        (**self).as_mut()
45    }
46    fn extend(&mut self, len: usize) -> Result<(), ()> {
47        (**self).extend(len)
48    }
49}
50
51// impl for array
52unsafe impl<T: MemPod, const CAP: usize> DstBuf for [MaybeUninit<T>; CAP] {
53    type Inner = T;
54
55    fn as_ref(&self) -> &[MaybeUninit<Self::Inner>] {
56        self
57    }
58    fn as_mut(&mut self) -> &mut [MaybeUninit<Self::Inner>] {
59        self
60    }
61    fn extend(&mut self, len: usize) -> Result<(), ()> {
62        if len > CAP { Err(()) } else { Ok(()) }
63    }
64}
65
66/// Vector backed structures, can be used to auto-grow the allocation
67///
68/// # Examples
69/// ```
70/// # use {devela::data::DstQueue, core::mem::MaybeUninit};
71/// let mut buf = DstQueue::<str, Vec<MaybeUninit<u8>>>::new();
72/// buf.push_back_str("Hello world!");
73/// buf.push_back_str("This is a very long string");
74/// buf.push_back_str("The buffer should keep growing as it needs to");
75/// for line in buf.iter() {
76///   println!("{}", line);
77/// }
78/// ```
79#[cfg(feature = "alloc")]
80#[cfg_attr(nightly_doc, doc(cfg(feature = "alloc")))]
81unsafe impl<T: MemPod> DstBuf for crate::Vec<MaybeUninit<T>> {
82    type Inner = T;
83    fn as_ref(&self) -> &[MaybeUninit<Self::Inner>] {
84        self
85    }
86    fn as_mut(&mut self) -> &mut [MaybeUninit<Self::Inner>] {
87        self
88    }
89    fn extend(&mut self, len: usize) -> Result<(), ()> {
90        if len > self.len() {
91            self.resize(len, MaybeUninit::uninit());
92            let cap = self.capacity();
93            self.resize(cap, MaybeUninit::uninit());
94        }
95        Ok(())
96    }
97}
98
99#[doc = crate::TAG_DATA_STRUCTURE!()]
100/// A static array for storing <abbr title="Dynamically sized type">DST</abbr>s.
101pub struct DstArray<T, const CAP: usize> {
102    inner: Array<MaybeUninit<T>, CAP>,
103}
104impl<T, const CAP: usize> Deref for DstArray<T, CAP> {
105    type Target = Array<MaybeUninit<T>, CAP>;
106
107    fn deref(&self) -> &Self::Target {
108        &self.inner
109    }
110}
111impl<T, const CAP: usize> DerefMut for DstArray<T, CAP> {
112    fn deref_mut(&mut self) -> &mut Self::Target {
113        &mut self.inner
114    }
115}
116impl<T: MemPod, const CAP: usize> Default for DstArray<T, CAP> {
117    fn default() -> Self {
118        Self { inner: Array::new([MaybeUninit::uninit(); CAP]) }
119    }
120}
121impl<T: MemPod, const CAP: usize> ConstDefault for DstArray<T, CAP> {
122    const DEFAULT: Self = Self {
123        inner: Array::new_bare([MaybeUninit::uninit(); CAP]),
124    };
125}
126#[rustfmt::skip]
127unsafe impl<T: MemPod, const CAP: usize> DstBuf for DstArray<T, CAP> {
128    type Inner = T;
129    fn as_ref(&self) -> &[MaybeUninit<Self::Inner>] {
130        &self.inner
131    }
132    fn as_mut(&mut self) -> &mut [MaybeUninit<Self::Inner>] {
133        &mut self.inner
134    }
135    fn extend(&mut self, len: usize) -> Result<(), ()> {
136        if len > CAP { Err(()) } else { Ok(()) }
137    }
138}
139
140#[doc = crate::TAG_DATA_STRUCTURE!()]
141/// A statically allocated buffer for storing <abbr title="Dynamically sized
142/// type">DST</abbr>s with pointer alignment.
143pub type DstArrayUsize<const CAP: usize> = DstArray<usize, CAP>;
144
145#[doc = crate::TAG_DATA_STRUCTURE!()]
146/// A dynamically allocated buffer for storing <abbr title="Dynamically sized
147/// type">DST</abbr>s with pointer alignment.
148#[cfg(feature = "alloc")]
149#[cfg_attr(nightly_doc, doc(cfg(feature = "alloc")))]
150pub type DstVecUsize = crate::Vec<MaybeUninit<usize>>;
151
152// MAYBE
153// /// A DST buffer backing onto a Vec.
154// #[cfg(feature = "alloc")]
155// #[cfg_attr(nightly_doc, doc(cfg(feature = "alloc")))]
156// pub struct DstVec<T: MemPod>(crate::Vec<MaybeUninit<T>>);
157// impl<T: MemPod> Deref for DstVec<T> {
158//     type Target = Vec<MaybeUninit<T>>;
159//
160//     fn deref(&self) -> &Self::Target {
161//         &self.0
162//     }
163// }
164// impl<T: MemPod> DerefMut for DstVec<T> {
165//     fn deref_mut(&mut self) -> &mut Self::Target {
166//         &mut self.0
167//     }
168// }