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'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}