Skip to main content

devela/data/layout/dst/
buffer.rs

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