arraylib/ext/
slice_ext.rs

1use core::mem::MaybeUninit;
2
3use crate::{iter::ArrayWindows, Array, ArrayExt, SizeError};
4
5/// Extension for [`slice`]
6///
7/// [`slice`]: core::slice
8pub trait Slice {
9    /// Item of the slice, i.e.
10    /// ```
11    /// # use arraylib::Slice; fn dummy<T>() where
12    /// [T]: Slice<Item = T>
13    /// # {}
14    /// ```
15    type Item;
16
17    /// Copy `self` into an owned array.
18    /// Return `Err(SizeError)` if len of `self` is not equal to `A::SIZE`.
19    ///
20    /// ## Examples
21    ///
22    /// ```
23    /// use arraylib::Slice;
24    ///
25    /// let slice: &[i32] = &[0, 1, 2, 3, 4];
26    /// let array: [i32; 5] = slice.copied().unwrap();
27    /// assert_eq!(array, [0, 1, 2, 3, 4]);
28    /// ```
29    ///
30    /// ```
31    /// use arraylib::{SizeError, Slice};
32    ///
33    /// let slice: &[i32] = &[0, 1, 2, 3, 4];
34    /// let result = slice.copied::<[i32; 2]>();
35    /// assert_eq!(result, Err(SizeError::default()));
36    /// ```
37    fn copied<A>(&self) -> Result<A, SizeError>
38    where
39        A: Array<Item = Self::Item>,
40        A::Item: Copy;
41
42    /// Clone `self` into an owned array.
43    /// Return `Err(SizeError)` if len of `self` is not equal to `A::SIZE`.
44    ///
45    /// ## Examples
46    ///
47    /// ```
48    /// use arraylib::Slice;
49    /// use core::ops::Range;
50    ///
51    /// // Range is not `Copy`
52    /// let slice: &[Range<usize>] = &[0..1, 1..3, 2..10];
53    /// let array: [Range<usize>; 3] = slice.cloned().unwrap();
54    /// assert_eq!(array, [0..1, 1..3, 2..10]);
55    /// ```
56    ///
57    /// ```
58    /// use arraylib::{SizeError, Slice};
59    /// use core::ops::Range;
60    ///
61    /// let slice: &[Range<usize>] = &[0..1, 1..3, 2..10];
62    /// let result = slice.cloned::<[Range<usize>; 5]>();
63    /// assert_eq!(result, Err(SizeError::default()));
64    /// ```
65    fn cloned<A>(&self) -> Result<A, SizeError>
66    where
67        A: Array<Item = Self::Item>,
68        A::Item: Clone;
69
70    /// Returns an iterator over all contiguous windows of type `A` (length
71    /// `A::SIZE`). The windows overlap. If the slice is shorter than size
72    /// (`A::SIZE`), the iterator returns `None`.
73    ///
74    /// ## Panics
75    ///
76    /// Panics if `A::SIZE` is 0 (`A = [T; 0]`).
77    ///
78    /// ## Examples
79    ///
80    /// ```
81    /// use arraylib::Slice;
82    ///
83    /// let mut iter = [1, 2, 3, 4].array_windows::<[_; 2]>();
84    /// assert_eq!(iter.next(), Some(&[1, 2]));
85    /// assert_eq!(iter.next(), Some(&[2, 3]));
86    /// assert_eq!(iter.next(), Some(&[3, 4]));
87    /// assert_eq!(iter.next(), None);
88    /// ```
89    ///
90    /// In difference with [`<[T]>::windows`], this method returns iterator that
91    /// returns _arrays_, so you can use array destruction:
92    ///
93    /// [`<[T]>::windows`]: https://doc.rust-lang.org/std/primitive.slice.html#method.windows
94    ///
95    /// ```
96    /// use arraylib::Slice;
97    ///
98    /// assert_eq!(
99    ///     [1, 2, 3, 4, 5]
100    ///         .array_windows::<[u32; 3]>()
101    ///         .map(|[a, b, c]| a + b + c)
102    ///         .sum::<u32>(),
103    ///     27
104    /// )
105    /// ```
106    ///
107    /// If the slice is shorter than size:
108    ///
109    /// ```
110    /// use arraylib::Slice;
111    ///
112    /// let slice = ['f', 'o', 'o'];
113    /// let mut iter = slice.array_windows::<[_; 4]>();
114    /// assert!(iter.next().is_none());
115    /// ```
116    fn array_windows<A>(&self) -> ArrayWindows<A>
117    where
118        A: Array<Item = Self::Item>;
119}
120
121/// Extension for maybe uninitialized slices (`[MaybeUninit<_>]`)
122pub trait MaybeUninitSlice:
123    Slice<Item = MaybeUninit<<Self as MaybeUninitSlice>::InitItem>>
124{
125    /// Initialized item i.e.
126    /// ```
127    /// # use std::mem::MaybeUninit;
128    /// # use arraylib::MaybeUninitSlice;
129    /// # fn dummy<T>()
130    /// # where
131    /// [MaybeUninit<T>]: MaybeUninitSlice<InitItem = T>
132    /// # {}
133    /// ```
134    type InitItem;
135
136    /// Assume that all items of self are initialized
137    ///
138    /// ## Safety
139    ///
140    /// It is up to the caller to guarantee that all elements of the array are
141    /// really in an initialized state. Calling this when the content is not
142    /// yet fully initialized causes immediate undefined behavior. The
143    /// [`MaybeUninit's` type-level documentation][inv] contains
144    /// more information about this initialization invariant.
145    ///
146    /// See also [`MaybeUninit::assume_init`] documentation.
147    ///
148    /// [inv]: core::mem#initialization-invariant
149    /// [`MaybeUninit::assume_init`]: core::mem::MaybeUninit::assume_init
150    unsafe fn assume_init(&self) -> &[Self::InitItem];
151
152    /// Assume that all items of self are initialized
153    ///
154    /// ## Safety
155    ///
156    /// It is up to the caller to guarantee that all elements of the array are
157    /// really in an initialized state. Calling this when the content is not
158    /// yet fully initialized causes immediate undefined behavior. The
159    /// [`MaybeUninit's` type-level documentation][inv] contains
160    /// more information about this initialization invariant.
161    ///
162    /// See also [`MaybeUninit::assume_init`] documentation.
163    ///
164    /// [inv]: core::mem#initialization-invariant
165    /// [`MaybeUninit::assume_init`]: core::mem::MaybeUninit::assume_init
166    unsafe fn assume_init_mut(&mut self) -> &mut [Self::InitItem];
167}
168
169impl<T> Slice for [T] {
170    type Item = T;
171
172    #[inline]
173    fn copied<A>(&self) -> Result<A, SizeError>
174    where
175        A: Array<Item = Self::Item>,
176        A::Item: Copy,
177    {
178        A::from_slice(self)
179    }
180
181    #[inline]
182    fn cloned<A>(&self) -> Result<A, SizeError>
183    where
184        A: Array<Item = Self::Item>,
185        A::Item: Clone,
186    {
187        A::clone_from_slice(self)
188    }
189
190    #[inline]
191    fn array_windows<A>(&self) -> ArrayWindows<A>
192    where
193        A: Array<Item = Self::Item>,
194    {
195        ArrayWindows::new(self)
196    }
197}
198
199impl<T> MaybeUninitSlice for [MaybeUninit<T>] {
200    type InitItem = T;
201
202    #[inline]
203    unsafe fn assume_init(&self) -> &[Self::InitItem] {
204        // # Unsafety
205        //
206        // Behavior is undefined if any of `MaybeUninit`s in `self` is in the
207        // `uninit` state
208        //ref_cast::<[MaybeUninit<T>], [T]>(self)
209        &*(self as *const [MaybeUninit<T>] as *const [T])
210    }
211
212    #[inline]
213    unsafe fn assume_init_mut(&mut self) -> &mut [Self::InitItem] {
214        // # Unsafety
215        //
216        // Behavior is undefined if any of `MaybeUninit`s in `self` is in the
217        // `uninit` state
218        &mut *(self as *mut [MaybeUninit<T>] as *mut [T])
219    }
220}