linearize/
storage.rs

1use {
2    crate::Linearize,
3    core::{
4        array::TryFromSliceError,
5        borrow::{Borrow, BorrowMut},
6        cmp::Ordering,
7        hash::Hash,
8        mem::MaybeUninit,
9        ptr,
10    },
11};
12
13pub trait Storage<L, T>:
14    Sized
15    + AsRef<[T]>
16    + AsMut<[T]>
17    + Borrow<[T]>
18    + BorrowMut<[T]>
19    + IntoIterator<Item = T, IntoIter: ExactSizeIterator + DoubleEndedIterator>
20where
21    L: Linearize<Storage<T> = Self> + ?Sized,
22{
23    fn into_copy(self) -> L::CopyStorage<T>
24    where
25        T: Copy;
26
27    fn as_copy(&self) -> &L::CopyStorage<T>
28    where
29        T: Copy;
30
31    fn as_copy_mut(&mut self) -> &mut L::CopyStorage<T>
32    where
33        T: Copy;
34
35    fn into_storage(self) -> L::Storage<T>;
36
37    fn from_fn(cb: impl FnMut(usize) -> T) -> Self;
38
39    fn each_ref(&self) -> <L as Linearize>::Storage<&T>;
40
41    fn each_mut(&mut self) -> <L as Linearize>::Storage<&mut T>;
42
43    fn map<U>(self, cb: impl FnMut(usize, T) -> U) -> <L as Linearize>::Storage<U>;
44
45    fn clone(&self) -> Self
46    where
47        T: Clone;
48
49    fn clone_from(&mut self, source: &Self)
50    where
51        T: Clone;
52
53    fn default() -> Self
54    where
55        T: Default;
56
57    fn eq(&self, other: &Self) -> bool
58    where
59        T: PartialEq;
60
61    fn cmp(&self, other: &Self) -> Ordering
62    where
63        T: Ord;
64
65    fn max(self, other: Self) -> Self
66    where
67        T: Ord;
68
69    fn min(self, other: Self) -> Self
70    where
71        T: Ord;
72
73    fn clamp(self, min: Self, max: Self) -> Self
74    where
75        T: Ord;
76
77    fn partial_cmp(&self, other: &Self) -> Option<Ordering>
78    where
79        T: PartialOrd;
80
81    fn as_hash(&self) -> impl Hash
82    where
83        T: Hash;
84
85    fn ref_try_from(from: &[T]) -> Result<&Self, TryFromSliceError>;
86
87    fn mut_try_from(from: &mut [T]) -> Result<&mut Self, TryFromSliceError>;
88
89    fn copy_ref_try_from(from: &[T]) -> Result<Self, TryFromSliceError>
90    where
91        T: Copy;
92
93    fn copy_mut_try_from(from: &mut [T]) -> Result<Self, TryFromSliceError>
94    where
95        T: Copy;
96
97    #[cfg(feature = "std")]
98    fn vec_try_from(from: Vec<T>) -> Result<Self, Vec<T>>;
99}
100
101pub trait CopyStorage<L, T>: Copy
102where
103    L: Linearize<CopyStorage<T> = Self> + ?Sized,
104    T: Copy,
105{
106    fn into_storage(self) -> L::Storage<T>;
107
108    fn as_storage(&self) -> &L::Storage<T>;
109
110    fn as_storage_mut(&mut self) -> &mut L::Storage<T>;
111}
112
113impl<L, T, const N: usize> Storage<L, T> for [T; N]
114where
115    L: Linearize<Storage<T> = Self> + ?Sized,
116{
117    fn into_copy(self) -> L::CopyStorage<T>
118    where
119        T: Copy,
120    {
121        // Unnecessary because T: Copy and therefore [T; N] has no drop impl.
122        let slf = MaybeUninit::new(self);
123        unsafe {
124            // SAFETY:
125            // - L::Storage<T> = Self by the bounds of this impl.
126            // - L::Storage<T> = L::CopyStorage<T> by the definition of Linearize.
127            ptr::read(slf.as_ptr() as *const L::CopyStorage<T>)
128        }
129    }
130
131    fn as_copy(&self) -> &L::CopyStorage<T>
132    where
133        T: Copy,
134    {
135        unsafe {
136            // SAFETY:
137            // - L::Storage<T> = Self by the bounds of this impl.
138            // - L::Storage<T> = L::CopyStorage<T> by the definition of Linearize.
139            &*(self as *const L::Storage<T> as *const L::CopyStorage<T>)
140        }
141    }
142
143    fn as_copy_mut(&mut self) -> &mut L::CopyStorage<T>
144    where
145        T: Copy,
146    {
147        unsafe {
148            // SAFETY:
149            // - L::Storage<T> = Self by the bounds of this impl.
150            // - L::Storage<T> = L::CopyStorage<T> by the definition of Linearize.
151            &mut *(self as *mut L::Storage<T> as *mut L::CopyStorage<T>)
152        }
153    }
154
155    fn into_storage(self) -> L::Storage<T> {
156        self
157    }
158
159    fn from_fn(cb: impl FnMut(usize) -> T) -> Self {
160        core::array::from_fn(cb)
161    }
162
163    fn each_ref(&self) -> L::Storage<&T> {
164        let res: [&T; N] = <[T; N]>::each_ref(self);
165        unsafe {
166            // SAFETY:
167            // - L::Storage<X> is required to be [X; L::LENGTH].
168            // - L::Storage<T> = Self = [T; N] by the where clause of this impl.
169            // - With X = T it follows that L::LENGTH = N;
170            // - With X = &T it follows that L::Storage<&T> = [&T; L::LENGTH] = [&T; N].
171            ptr::read(&res as *const [&T; N] as *const L::Storage<&T>)
172        }
173    }
174
175    fn each_mut(&mut self) -> L::Storage<&mut T> {
176        let res: [&mut T; N] = <[T; N]>::each_mut(self);
177        let res: MaybeUninit<[&mut T; N]> = MaybeUninit::new(res);
178        unsafe {
179            // SAFETY:
180            // - L::Storage<X> is required to be [X; L::LENGTH].
181            // - L::Storage<T> = [T; N] by the where clause of this impl.
182            // - L::Storage<T> = Self = [T; N] by the where clause of this impl.
183            // - With X = T it follows that L::LENGTH = N;
184            // - With X = &mut T it follows that L::Storage<&mut T> = [&mut T; L::LENGTH] = [&mut T; N].
185            ptr::read(res.as_ptr() as *const L::Storage<&mut T>)
186        }
187    }
188
189    fn map<U>(self, mut cb: impl FnMut(usize, T) -> U) -> L::Storage<U> {
190        let mut src = MaybeUninit::<[T; N]>::new(self);
191        let src_ptr = src.as_mut_ptr() as *const T;
192        let mut res;
193        let res_ptr;
194        if size_of::<U>() <= size_of::<T>() && align_of::<U>() <= align_of::<T>() {
195            // CASE: map-in-place
196            res_ptr = src_ptr as *mut U;
197        } else {
198            // CASE: map-in-new-place
199            res = MaybeUninit::<[U; N]>::uninit();
200            res_ptr = res.as_mut_ptr() as *mut U;
201        }
202        for i in 0..N {
203            let t = unsafe {
204                // SAFETY:
205                // - src_ptr points to [T; N] and i < N.
206                // - Each array element is read at most once.
207                // - In map-in-new-place case, the array is not written to.
208                // - In map-in-place case, only U's with index < i have been written so far
209                //   and since size_of::<U> <= size_of::<T>, no bytes of the i'th element
210                //   have been written to.
211                ptr::read(src_ptr.add(i))
212            };
213            let u = cb(i, t);
214            unsafe {
215                // SAFETY:
216                // - In map-in-new-place case: res_ptr points memory suitable for [U; N].
217                // - In map-in-place case: res_ptr points to [T; N] and
218                //   size_of::<U> <= size_of::<T> and align_of::<U> <= align_of::<T>.
219                //   Therefore, the pointed to object is also suitable to hold a [U; N].
220                ptr::write(res_ptr.add(i), u);
221            }
222        }
223        unsafe {
224            // SAFETY:
225            // - res_ptr points to an object suitable to hold a [U; N]. See the safety
226            //   docs for ptr::write above.
227            // - This array has been initialized for each i in [0; N).
228            // - L::Storage<X> = [X; N] by the where clause of this impl.
229            // - With X = T it follows that L::LENGTH = N;
230            // - With X = U it follows that L::Storage<U> = [U; L::LENGTH] = [U; N].
231            ptr::read(res_ptr as *const L::Storage<U>)
232        }
233    }
234
235    fn clone(&self) -> Self
236    where
237        T: Clone,
238    {
239        <[T; N] as Clone>::clone(self)
240    }
241
242    fn clone_from(&mut self, source: &Self)
243    where
244        T: Clone,
245    {
246        <[T; N] as Clone>::clone_from(self, source)
247    }
248
249    fn default() -> Self
250    where
251        T: Default,
252    {
253        core::array::from_fn(|_| T::default())
254    }
255
256    fn eq(&self, other: &Self) -> bool
257    where
258        T: PartialEq,
259    {
260        <[T; N] as PartialEq>::eq(self, other)
261    }
262
263    fn cmp(&self, other: &Self) -> Ordering
264    where
265        T: Ord,
266    {
267        <[T; N] as Ord>::cmp(self, other)
268    }
269
270    fn max(self, other: Self) -> Self
271    where
272        T: Ord,
273    {
274        <[T; N] as Ord>::max(self, other)
275    }
276
277    fn min(self, other: Self) -> Self
278    where
279        T: Ord,
280    {
281        <[T; N] as Ord>::min(self, other)
282    }
283
284    fn clamp(self, min: Self, max: Self) -> Self
285    where
286        T: Ord,
287    {
288        <[T; N] as Ord>::clamp(self, min, max)
289    }
290
291    fn partial_cmp(&self, other: &Self) -> Option<Ordering>
292    where
293        T: PartialOrd,
294    {
295        <[T; N] as PartialOrd>::partial_cmp(self, other)
296    }
297
298    fn as_hash(&self) -> impl Hash
299    where
300        T: Hash,
301    {
302        self
303    }
304
305    fn ref_try_from(from: &[T]) -> Result<&Self, TryFromSliceError> {
306        <&[T; N] as TryFrom<&[T]>>::try_from(from)
307    }
308
309    fn mut_try_from(from: &mut [T]) -> Result<&mut Self, TryFromSliceError> {
310        <&mut [T; N] as TryFrom<&mut [T]>>::try_from(from)
311    }
312
313    fn copy_ref_try_from(from: &[T]) -> Result<Self, TryFromSliceError>
314    where
315        T: Copy,
316    {
317        <[T; N] as TryFrom<&[T]>>::try_from(from)
318    }
319
320    fn copy_mut_try_from(from: &mut [T]) -> Result<Self, TryFromSliceError>
321    where
322        T: Copy,
323    {
324        <[T; N] as TryFrom<&mut [T]>>::try_from(from)
325    }
326
327    #[cfg(feature = "std")]
328    fn vec_try_from(from: Vec<T>) -> Result<Self, Vec<T>> {
329        <[T; N] as TryFrom<Vec<T>>>::try_from(from)
330    }
331}
332
333impl<L, T, const N: usize> CopyStorage<L, T> for [T; N]
334where
335    L: Linearize<Storage<T> = Self, CopyStorage<T> = Self> + ?Sized,
336    T: Copy,
337{
338    fn into_storage(self) -> L::Storage<T> {
339        self
340    }
341
342    fn as_storage(&self) -> &L::Storage<T> {
343        self
344    }
345
346    fn as_storage_mut(&mut self) -> &mut L::Storage<T> {
347        self
348    }
349}