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}