devela/sys/mem/storage/
bare.rs

1// devela::sys::mem::storage::bare
2//
3//! *Bare* storage doesn't affect its contents
4//
5// API based on https://doc.rust-lang.org/alloc/boxed/struct.Box.html
6
7#[cfg(all(doc, feature = "alloc"))]
8use crate::{Box, Boxed};
9use crate::{Mem, Storage};
10// #[cfg(feature = "dep_rkyv")] // DEP_DISABLED
11// use rkyv::{Archive, Deserialize, Serialize};
12
13/// <span class='stab portability' title='re-exported from rust&#39;s `core`'>`core`</span>
14/// A zero-sized marker for a [`Storage`] type that wraps its data in a [`BareBox`].
15///
16/// Equivalent to the [`Boxed`] marker struct which uses a [`Box`] for the underlying storage.
17pub type Bare = ();
18
19/// A no-op pointer type, like a [`Box`] but without affecting how `T` is stored.
20///
21/// It is used as the underlying [`Storage`] for the [`Bare`] marker
22/// struct, just as a [`Box`] is used as the storage for [`Boxed`].
23///
24/// # Examples
25/// ```
26/// # use devela::BareBox;
27/// let byte = BareBox::new(0_u8);
28/// ```
29// #[cfg_attr(feature = "dep_rkyv", derive(Archive, Serialize, Deserialize))]
30pub struct BareBox<T>(pub T);
31
32/// A zero-sized marker for a storage type that wraps its data in a [`BareBox`].
33///
34/// This implementation is equivalent to the one for [`Boxed`] which uses [`Box`] for storage.
35#[rustfmt::skip]
36impl Storage for Bare {
37    type Stored<T> = BareBox<T>;
38    fn name() -> &'static str { "BareBox" }
39}
40
41#[rustfmt::skip]
42impl<T> BareBox<T> {
43    /// Creates a new `BareBox` storage for the given `t`.
44    #[must_use]
45    pub const fn new(t: T) -> Self { Self(t) }
46
47    /// Returns the inner stored type.
48    ///
49    /// Example
50    /// ```
51    /// # use devela::BareBox;
52    /// let b = BareBox::new(42);
53    /// let inner = b.into_inner();
54    /// assert_eq!(42, inner);
55    /// ```
56    #[must_use]
57    pub fn into_inner(self) -> T { self.0 }
58
59    /// Returns a shared reference to the inner stored type, in compile-time.
60    ///
61    /// Example
62    /// ```
63    /// # use devela::BareBox;
64    /// const B: BareBox<char> = BareBox::new('a');
65    /// const REF: &char = B.as_ref();
66    /// assert_eq!('a', *REF);
67    /// ```
68    #[must_use]
69    pub const fn as_ref(&self) -> &T { &self.0 }
70
71    /// Returns an exclusive reference to the inner stored type, in compile-time.
72    ///
73    /// Example
74    /// ```
75    /// # use devela::BareBox;
76    /// const fn modify_value(mut b: BareBox<char>) -> BareBox<char> {
77    ///     let mb = b.as_mut();
78    ///     *mb = 'z';
79    ///     b
80    /// }
81    /// const MODIFIED: BareBox<char> = modify_value(BareBox::new('a'));
82    /// assert_eq!('z', *MODIFIED);
83    /// ```
84    #[must_use]
85    pub const fn as_mut(&mut self) -> &mut T { &mut self.0 }
86
87    /// Replaces the stored value with a `new` one, returning the old value.
88    ///
89    /// Example
90    /// ```
91    /// # use devela::BareBox;
92    /// let mut b = BareBox::new(42);
93    /// let old = b.replace(100);
94    /// assert_eq!(42, old);
95    /// assert_eq!(100, *b);
96    /// ```
97    #[must_use]
98    pub fn replace(&mut self, mut new: T) -> T {
99        Mem::swap(&mut self.0, &mut new); new
100    }
101
102    /// Checks if the stored value is the default.
103    ///
104    /// Example
105    /// ```
106    /// # use devela::BareBox;
107    /// let b = BareBox::new(0);
108    /// assert!(b.is_default());
109    /// ```
110    #[must_use]
111    pub fn is_default(&self) -> bool where T: Default + PartialEq {
112        self.0 == T::default()
113    }
114}
115
116#[rustfmt::skip]
117impl<T: Copy> BareBox<T> {
118    /// Returns the inner stored type in compile-time.
119    ///
120    /// Example
121    /// ```
122    /// # use devela::BareBox;
123    /// const B: BareBox<i32> = BareBox::new(42);
124    /// const I: i32 = B.into_inner_copy();
125    /// assert_eq!(42, I);
126    /// ```
127    #[must_use]
128    pub const fn into_inner_copy(self) -> T {
129        self.0
130    }
131
132    /// Maps the inner value to another type using the provided function.
133    ///
134    /// Example
135    /// ```
136    /// # use devela::BareBox;
137    /// let b = BareBox::new(2);
138    /// let squared = b.map(|x| x * x);
139    /// assert_eq!(4, *squared);
140    /// ```
141    pub fn map<U: Copy>(self, f: fn(T) -> U) -> BareBox<U> {
142        BareBox(f(self.0))
143    }
144}
145
146impl<T: Copy> BareBox<Option<T>> {
147    /// Unwraps the inner `Option`, returning the contained value or a default,
148    /// in compile time.
149    ///
150    /// Example
151    /// ```
152    /// # use devela::BareBox;
153    /// const B: BareBox<Option<char>> = BareBox::new(Some('a'));
154    /// const BU: char = B.unwrap_copy_or('c');
155    /// assert_eq!['a', BU];
156    ///
157    /// // We could also auto-dereference to Option::unwrap_or():
158    /// assert_eq!['a', B.unwrap_or('b')];
159    /// ```
160    #[rustfmt::skip]
161    pub const fn unwrap_copy_or(self, default: T) -> T {
162        match self.0 { Some(val) => val, None => default }
163    }
164}
165impl<T: Copy, E: Copy> BareBox<Result<T, E>> {
166    /// Unwraps the inner `Result`, returning the `Ok` value or a default,
167    /// in compile time.
168    ///
169    /// Example
170    /// ```
171    /// # use devela::BareBox;
172    /// const B: BareBox<Result<char, ()>> = BareBox::new(Ok('a'));
173    ///
174    /// const BU: char = B.unwrap_copy_or('c');
175    /// assert_eq!['a', BU];
176    ///
177    /// // We could also auto-dereference to Result::unwrap_or():
178    /// assert_eq!['a', B.unwrap_or('b')];
179    /// ```
180    #[rustfmt::skip]
181    pub const fn unwrap_copy_or(self, default: T) -> T {
182        match self.0 { Ok(val) => val, Err(_) => default }
183    }
184}
185
186mod core_impls {
187    use crate::{BareBox, ConstDefault};
188    use core::{cmp, convert, fmt, hash, ops};
189
190    impl<T> ops::Deref for BareBox<T> {
191        type Target = T;
192        fn deref(&self) -> &T {
193            &self.0
194        }
195    }
196    impl<T> ops::DerefMut for BareBox<T> {
197        fn deref_mut(&mut self) -> &mut T {
198            &mut self.0
199        }
200    }
201
202    impl<T> convert::AsRef<T> for BareBox<T> {
203        fn as_ref(&self) -> &T {
204            &self.0
205        }
206    }
207    impl<T> convert::AsMut<T> for BareBox<T> {
208        fn as_mut(&mut self) -> &mut T {
209            &mut self.0
210        }
211    }
212
213    impl<T> From<T> for BareBox<T> {
214        fn from(t: T) -> Self {
215            BareBox(t)
216        }
217    }
218
219    impl<T: Clone> Clone for BareBox<T> {
220        fn clone(&self) -> Self {
221            BareBox(self.0.clone())
222        }
223    }
224    impl<T: Copy> Copy for BareBox<T> {}
225
226    impl<T: Default> Default for BareBox<T> {
227        fn default() -> Self {
228            BareBox(T::default())
229        }
230    }
231
232    impl<T: ConstDefault> ConstDefault for BareBox<T> {
233        const DEFAULT: Self = BareBox(T::DEFAULT);
234    }
235
236    impl<T: PartialEq> PartialEq for BareBox<T> {
237        fn eq(&self, other: &Self) -> bool {
238            self.0.eq(&other.0)
239        }
240    }
241    impl<T: Eq> Eq for BareBox<T> {}
242
243    impl<T: PartialOrd> PartialOrd for BareBox<T> {
244        fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
245            self.0.partial_cmp(&other.0)
246        }
247    }
248    impl<T: Ord> Ord for BareBox<T> {
249        fn cmp(&self, other: &Self) -> cmp::Ordering {
250            self.0.cmp(&other.0)
251        }
252    }
253
254    impl<T: fmt::Debug> fmt::Debug for BareBox<T> {
255        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256            fmt::Debug::fmt(&self.0, f)
257        }
258    }
259    impl<T: fmt::Display> fmt::Display for BareBox<T> {
260        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261            fmt::Display::fmt(&self.0, f)
262        }
263    }
264
265    impl<T: fmt::Pointer> fmt::Pointer for BareBox<T> {
266        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267            fmt::Pointer::fmt(&self.0, f)
268        }
269    }
270
271    impl<T: hash::Hash> hash::Hash for BareBox<T> {
272        fn hash<H: hash::Hasher>(&self, state: &mut H) {
273            self.0.hash(state);
274        }
275    }
276    impl<T: hash::Hasher> hash::Hasher for BareBox<T> {
277        fn finish(&self) -> u64 {
278            self.0.finish()
279        }
280        fn write(&mut self, bytes: &[u8]) {
281            self.0.write(bytes);
282        }
283    }
284
285    impl<I: Iterator> Iterator for BareBox<I> {
286        type Item = I::Item;
287
288        fn next(&mut self) -> Option<I::Item> {
289            self.0.next()
290        }
291        fn size_hint(&self) -> (usize, Option<usize>) {
292            self.0.size_hint()
293        }
294        fn nth(&mut self, n: usize) -> Option<I::Item> {
295            self.0.nth(n)
296        }
297        fn last(self) -> Option<I::Item> {
298            self.0.last()
299        }
300    }
301
302    #[cfg(all(not(feature = "safe_mem"), feature = "unsafe_sync"))]
303    #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_sync")))]
304    unsafe impl<T: Send> Send for BareBox<T> {}
305
306    #[cfg(all(not(feature = "safe_mem"), feature = "unsafe_sync"))]
307    #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_sync")))]
308    unsafe impl<T: Sync> Sync for BareBox<T> {}
309}