ladata/list/array/
core_impls.rs

1// ladata::list::array::impls
2//
3//!
4//
5
6use crate::all::{Array, Direct, Storage};
7#[cfg(feature = "unsafe_init")]
8use core::mem::{self, MaybeUninit};
9use core::{
10    fmt,
11    ops::{Deref, DerefMut},
12};
13
14#[cfg(feature = "alloc")]
15use {
16    crate::mem::Boxed,
17    alloc::{boxed::Box, vec::Vec},
18};
19
20// Deref
21impl<T, S: Storage, const LEN: usize> Deref for Array<T, S, LEN> {
22    type Target = [T];
23
24    fn deref(&self) -> &Self::Target {
25        self.array.deref()
26    }
27}
28// DerefMut
29impl<T, S: Storage, const LEN: usize> DerefMut for Array<T, S, LEN> {
30    fn deref_mut(&mut self) -> &mut Self::Target {
31        self.array.deref_mut()
32    }
33}
34
35// T:Clone
36impl<T: Clone, S: Storage, const LEN: usize> Clone for Array<T, S, LEN>
37where
38    S::Stored<[T; LEN]>: Clone,
39{
40    fn clone(&self) -> Self {
41        Self {
42            array: self.array.clone(),
43        }
44    }
45}
46
47// T:Copy
48impl<T: Copy, S: Storage, const LEN: usize> Copy for Array<T, S, LEN> where S::Stored<[T; LEN]>: Copy
49{}
50
51// T:Debug
52impl<T: fmt::Debug, S: Storage, const LEN: usize> fmt::Debug for Array<T, S, LEN>
53where
54    S::Stored<[T; LEN]>: fmt::Debug,
55{
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        let mut debug = f.debug_struct(stringify![Array]);
58        debug.field("LEN", &LEN);
59        debug.field("", &self.array);
60        debug.finish()
61    }
62}
63
64// T:PartialEq
65impl<T: PartialEq, S: Storage, const LEN: usize> PartialEq for Array<T, S, LEN>
66where
67    S::Stored<[T; LEN]>: PartialEq,
68{
69    fn eq(&self, other: &Self) -> bool {
70        self.array == other.array && self.len() == other.len()
71    }
72}
73// T:Eq
74impl<T: Eq, S: Storage, const LEN: usize> Eq for Array<T, S, LEN> where S::Stored<[T; LEN]>: Eq {}
75
76// S:() + T:Default
77impl<T: Default, const LEN: usize> Default for Array<T, (), LEN> {
78    /// Returns an empty array, allocated in the stack,
79    /// using the default value to fill the remaining free data.
80    fn default() -> Self {
81        #[cfg(feature = "unsafe_init")]
82        let data = {
83            let mut arr: [MaybeUninit<T>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
84            for i in &mut arr[..] {
85                let _ = i.write(T::default());
86            }
87            unsafe { mem::transmute_copy::<_, [T; LEN]>(&arr) }
88        };
89
90        #[cfg(not(feature = "unsafe_init"))]
91        let data = core::array::from_fn(|_| T::default());
92
93        Array {
94            array: Direct::new(data),
95        }
96    }
97}
98
99// S:Boxed + T:Default
100#[cfg(feature = "alloc")]
101#[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
102impl<T: Default, const LEN: usize> Default for Array<T, Boxed, LEN> {
103    /// Returns an empty array, allocated in the heap,
104    /// using the default value to fill the remaining free data.
105    ///
106    /// # Examples
107    /// ```
108    /// use ladata::list::BoxedArray;
109    ///
110    /// let mut s = BoxedArray::<i32, 100>::default();
111    /// ```
112    fn default() -> Self {
113        #[cfg(not(feature = "unsafe_init"))]
114        let data = {
115            let mut v = Vec::<T>::with_capacity(LEN);
116
117            for _ in 0..LEN {
118                v.push(T::default());
119            }
120
121            let Ok(array) = v.into_boxed_slice().try_into() else {
122                panic!("Can't turn the boxed slice into a boxed array");
123            };
124            array
125        };
126
127        #[cfg(feature = "unsafe_init")]
128        let data = {
129            let mut v = Vec::<T>::with_capacity(LEN);
130
131            for _ in 0..LEN {
132                v.push(T::default());
133            }
134
135            let slice = v.into_boxed_slice();
136            let raw_slice = Box::into_raw(slice);
137            // SAFETY: pointer comes from using `into_raw`, and capacity is right.
138            unsafe { Box::from_raw(raw_slice as *mut [T; LEN]) }
139        };
140
141        Array { array: data }
142    }
143}
144
145impl<T, const LEN: usize> From<Array<T, (), LEN>> for [T; LEN] {
146    fn from(array: Array<T, (), LEN>) -> [T; LEN] {
147        array.array.0
148    }
149}
150#[cfg(feature = "alloc")]
151#[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
152impl<T, const LEN: usize> From<Array<T, Boxed, LEN>> for Box<[T; LEN]> {
153    fn from(array: Array<T, Boxed, LEN>) -> Box<[T; LEN]> {
154        array.array
155    }
156}
157
158impl<T: Default, I, const LEN: usize> From<I> for Array<T, (), LEN>
159where
160    I: IntoIterator<Item = T>,
161{
162    /// Returns a array filled with an iterator, in the stack.
163    ///
164    /// If the `iterator` length is less than the array length `LEN`,
165    /// the missing elements will be the default value of `T`.
166    ///
167    /// # Examples
168    /// ```
169    /// use ladata::list::DirectArray;
170    ///
171    /// let s: DirectArray<_, 4> = [1, 2, 3].into();
172    ///
173    /// assert_eq![s.as_slice(), &[1, 2, 3, 0]];
174    /// ```
175    fn from(iterator: I) -> Array<T, (), LEN> {
176        let mut iterator = iterator.into_iter();
177
178        #[cfg(feature = "unsafe_init")]
179        let data = {
180            let mut arr: [MaybeUninit<T>; LEN] = unsafe { MaybeUninit::uninit().assume_init() };
181            for i in &mut arr[..] {
182                if let Some(e) = iterator.next() {
183                    let _ = i.write(e);
184                } else {
185                    let _ = i.write(T::default());
186                }
187            }
188            unsafe { mem::transmute_copy::<_, [T; LEN]>(&arr) }
189        };
190
191        #[cfg(not(feature = "unsafe_init"))]
192        let data = core::array::from_fn(|_| {
193            if let Some(e) = iterator.next() {
194                e
195            } else {
196                T::default()
197            }
198        });
199
200        Array {
201            array: Direct::new(data),
202        }
203    }
204}
205
206#[cfg(feature = "alloc")]
207#[cfg_attr(feature = "nightly", doc(cfg(feature = "alloc")))]
208impl<T: Default, I, const LEN: usize> From<I> for Array<T, Boxed, LEN>
209where
210    I: IntoIterator<Item = T>,
211{
212    /// Returns a array filled with an iterator, in the heap.
213    ///
214    /// # Examples
215    /// ```
216    /// use ladata::list::BoxedArray;
217    ///
218    /// let s: BoxedArray<_, 4> = [1, 2, 3].into();
219    ///
220    /// assert_eq![s.as_slice(), &[1, 2, 3, 0]];
221    /// ```
222    fn from(iterator: I) -> Array<T, Boxed, LEN> {
223        let mut iterator = iterator.into_iter();
224
225        #[cfg(not(feature = "unsafe_init"))]
226        let data = {
227            let mut v = Vec::<T>::with_capacity(LEN);
228
229            for _ in 0..LEN {
230                if let Some(e) = iterator.next() {
231                    v.push(e);
232                } else {
233                    v.push(T::default());
234                }
235            }
236            let Ok(array) = v.into_boxed_slice().try_into() else {
237                panic!("Can't turn the boxed slice into a boxed array");
238            };
239            array
240        };
241
242        #[cfg(feature = "unsafe_init")]
243        let data = {
244            let mut v = Vec::<T>::with_capacity(LEN);
245
246            for _ in 0..LEN {
247                if let Some(e) = iterator.next() {
248                    v.push(e);
249                } else {
250                    v.push(T::default());
251                }
252            }
253            let slice = v.into_boxed_slice();
254            let raw_slice = Box::into_raw(slice);
255            // SAFETY: pointer comes from using `into_raw`, and capacity is right.
256            unsafe { Box::from_raw(raw_slice as *mut [T; LEN]) }
257        };
258
259        Array { array: data }
260    }
261}