1use core::fmt;
4use std::iter::FilterMap;
5use std::num::NonZeroUsize;
6use std::ops::Index;
7use std::slice::Chunks;
8
9use crate::iter::IntoNonEmptyIterator;
10use crate::iter::NonEmptyIterator;
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
24pub struct NESlice<'a, T> {
25 inner: &'a [T],
26}
27
28impl<'a, T> NESlice<'a, T> {
29 #[must_use]
31 pub const fn first(&self) -> &T {
32 &self.inner[0]
33 }
34
35 #[must_use]
38 pub const fn try_from_slice(slice: &'a [T]) -> Option<Self> {
39 if slice.is_empty() {
40 None
41 } else {
42 Some(NESlice { inner: slice })
43 }
44 }
45
46 #[must_use]
47 pub(crate) const unsafe fn from_slice_unchecked(slice: &'a [T]) -> Self {
48 NESlice { inner: slice }
49 }
50
51 #[must_use]
53 pub fn len(&self) -> NonZeroUsize {
54 debug_assert!(!self.inner.is_empty());
55 unsafe { NonZeroUsize::new_unchecked(self.inner.len()) }
56 }
57
58 #[deprecated(note = "A NESlice is never empty.")]
60 #[must_use]
61 pub const fn is_empty(&self) -> bool {
62 false
63 }
64
65 pub fn iter(&self) -> std::slice::Iter<'_, T> {
69 self.inner.iter()
70 }
71
72 pub fn nonempty_iter(&self) -> Iter<'_, T> {
74 Iter {
75 iter: self.inner.iter(),
76 }
77 }
78
79 pub fn nonempty_chunks(&'a self, chunk_size: NonZeroUsize) -> NEChunks<'a, T> {
106 NEChunks {
107 inner: self.inner.chunks(chunk_size.get()),
108 }
109 }
110}
111
112impl<T> AsRef<[T]> for NESlice<'_, T> {
113 fn as_ref(&self) -> &[T] {
114 self.inner
115 }
116}
117
118impl<'a, T> IntoNonEmptyIterator for NESlice<'a, T> {
119 type IntoNEIter = Iter<'a, T>;
120
121 fn into_nonempty_iter(self) -> Self::IntoNEIter {
122 Iter {
123 iter: self.inner.iter(),
124 }
125 }
126}
127
128impl<'a, T> IntoNonEmptyIterator for &'a NESlice<'a, T> {
129 type IntoNEIter = Iter<'a, T>;
130
131 fn into_nonempty_iter(self) -> Self::IntoNEIter {
132 self.nonempty_iter()
133 }
134}
135
136impl<'a, T> IntoIterator for NESlice<'a, T> {
137 type Item = &'a T;
138
139 type IntoIter = std::slice::Iter<'a, T>;
140
141 fn into_iter(self) -> Self::IntoIter {
142 self.inner.iter()
143 }
144}
145
146impl<'a, T> IntoIterator for &'a NESlice<'a, T> {
147 type Item = &'a T;
148
149 type IntoIter = std::slice::Iter<'a, T>;
150
151 fn into_iter(self) -> Self::IntoIter {
152 self.iter()
153 }
154}
155
156impl<T> Index<usize> for NESlice<'_, T> {
157 type Output = T;
158
159 fn index(&self, index: usize) -> &Self::Output {
160 &self.inner[index]
161 }
162}
163
164#[derive(Debug)]
166#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
167pub struct Iter<'a, T: 'a> {
168 iter: std::slice::Iter<'a, T>,
169}
170
171impl<T> NonEmptyIterator for Iter<'_, T> {}
172
173impl<'a, T> IntoIterator for Iter<'a, T> {
174 type Item = &'a T;
175
176 type IntoIter = std::slice::Iter<'a, T>;
177
178 fn into_iter(self) -> Self::IntoIter {
179 self.iter
180 }
181}
182
183#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
185pub struct NEChunks<'a, T> {
186 pub(crate) inner: Chunks<'a, T>,
187}
188
189type SliceFilter<'a, T> = fn(&'a [T]) -> Option<NESlice<'a, T>>;
190
191impl<T> NonEmptyIterator for NEChunks<'_, T> {}
192
193impl<'a, T> IntoIterator for NEChunks<'a, T> {
194 type Item = NESlice<'a, T>;
195
196 type IntoIter = FilterMap<Chunks<'a, T>, SliceFilter<'a, T>>;
197
198 fn into_iter(self) -> Self::IntoIter {
199 self.inner.filter_map(|x| NESlice::try_from_slice(x))
200 }
201}
202
203impl<T: fmt::Debug> fmt::Debug for NEChunks<'_, T> {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 self.inner.fmt(f)
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use std::num::NonZeroUsize;
212
213 use crate::nev;
214 use crate::slice::NEChunks;
215 use crate::NESlice;
216 use crate::NEVec;
217 use crate::NonEmptyIterator;
218
219 #[test]
220 fn test_from_conversion() {
221 let slice = [1, 2, 3, 4, 5];
222 let nonempty_slice = NESlice::try_from_slice(&slice);
223 let nonempty_slice = nonempty_slice.unwrap();
224
225 assert_eq!(nonempty_slice.inner, &[1, 2, 3, 4, 5]);
226 }
227
228 #[test]
229 fn test_iter_syntax() {
230 let slice = [0, 1, 2, 3];
231 let nonempty = NESlice::try_from_slice(&slice);
232 if let Some(nonempty) = nonempty {
233 for n in &nonempty {
234 assert_eq!(*n, *n); }
236 }
237 }
238
239 #[test]
240 fn test_into_nonempty_iter() {
241 use crate::IntoNonEmptyIterator;
242 use crate::NonEmptyIterator;
243 let slice = [0usize, 1, 2, 3];
244 let nonempty = NESlice::try_from_slice(&slice).unwrap();
245 for (i, n) in nonempty.into_nonempty_iter().enumerate() {
246 assert_eq!(i, *n);
247 }
248 }
249
250 #[test]
251 fn chunks() {
252 let v = nev![1, 2, 3, 4, 5, 6, 7];
253
254 let n = NonZeroUsize::new(3).unwrap();
255 let a: Vec<_> = v.nonempty_chunks(n).collect();
256
257 assert_eq!(
258 a,
259 vec![
260 nev![1, 2, 3].as_nonempty_slice(),
261 nev![4, 5, 6].as_nonempty_slice(),
262 nev![7].as_nonempty_slice()
263 ]
264 );
265
266 let n = NonZeroUsize::new(1).unwrap();
267 let b: Vec<_> = v.nonempty_chunks(n).collect();
268
269 assert_eq!(
270 b,
271 vec![
272 nev![1].as_nonempty_slice(),
273 nev![2].as_nonempty_slice(),
274 nev![3].as_nonempty_slice(),
275 nev![4].as_nonempty_slice(),
276 nev![5].as_nonempty_slice(),
277 nev![6].as_nonempty_slice(),
278 nev![7].as_nonempty_slice(),
279 ]
280 );
281 }
282
283 #[test]
284 fn chunks_len() {
285 let v = nev![1, 2, 3];
286 let n = NonZeroUsize::new(3).unwrap();
287 let c = v.nonempty_chunks(n).count().get();
288 assert_eq!(c, 1);
289
290 let v = nev![1, 2, 3];
291 let n = NonZeroUsize::new(5).unwrap();
292 let c = v.nonempty_chunks(n).count().get();
293 assert_eq!(c, 1);
294
295 let v = nev![1, 2, 3, 4];
296 let n = NonZeroUsize::new(3).unwrap();
297 let c = v.nonempty_chunks(n).count().get();
298 assert_eq!(c, 2);
299 }
300
301 #[test]
305 fn chunks_into_iter_with_chunk_size_over_len() {
306 let v = nev![1, 2, 3];
307 let n = NonZeroUsize::new(4).unwrap();
308 let c = v.nonempty_chunks(n);
309
310 for slice in c {
312 let _: NESlice<'_, i32> = slice;
313 }
314
315 let v = nev![1, 2, 3];
316 let n = NonZeroUsize::new(4).unwrap();
317 let c: NEVec<_> = v.nonempty_chunks(n).collect();
318
319 assert_eq!(1, c.len().get());
320 assert_eq!(&v.as_nonempty_slice(), c.first());
321 }
322
323 #[test]
325 fn chunks_into_iter_should_return_elements_exactly_once() {
326 let v = nev![1, 2, 3, 4, 5, 6, 57];
327 let n = NonZeroUsize::new(3).unwrap();
328 let c: NEChunks<'_, i32> = v.nonempty_chunks(n);
329
330 let mut r: Vec<NESlice<i32>> = vec![];
331
332 for slice in c {
333 let _: NESlice<'_, i32> = slice;
334 r.push(slice);
335 }
336
337 assert_eq!(
338 r,
339 vec![
340 nev![1, 2, 3].as_nonempty_slice(),
341 nev![4, 5, 6].as_nonempty_slice(),
342 nev![57].as_nonempty_slice(),
343 ]
344 );
345 }
346
347 #[test]
350 fn chunks_into_iter_edge_case_single_element() {
351 let v = nev![1];
352 let n = NonZeroUsize::new(3).unwrap();
353 let c: NEChunks<'_, i32> = v.nonempty_chunks(n);
354
355 let mut iter = c.into_iter();
356
357 let next = iter.next().unwrap();
358 assert_eq!(1, next.len().get());
359 assert!(iter.next().is_none());
360 }
361}