array_util/
lib.rs

1//! `no_std` array helpers available without nightly.
2//!
3//! ## Description
4//!
5//! Many useful array and slice methods are currently gated by nightly
6//! features, though their general functionality and interface is essentially
7//! stable. As such this crate provides stable alternatives to the following
8//! features, often the same underlying implementation as the current nightly
9//! version:
10//!
11//! - [`array_try_from_fn`]
12//! - [`array_try_map`]
13//! - [`array_chunks`]
14//! - [`slice_as_chunks`]
15//! - [`slice_flatten`]
16//!
17//! ## Usage
18//!
19//! Users can either import an `Ext` trait (`SliceExt`, `ArrayExt`, or
20//! `SliceOfArrayExt`) traits to bring in the desired methods, or use the bare
21//! functions. Note that trait methods have the `_ext` suffix to avoid
22//! collision with the core library methods.
23//!
24//! ```
25//! use array_util::ArrayExt;
26//!
27//! let a = ["1", "2", "3"];
28//! let b = a.try_map_ext(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
29//! assert_eq!(b, [2, 3, 4]);
30//!
31//! let a = ["1", "2a", "3"];
32//! let b = a.try_map_ext(|v| v.parse::<u32>());
33//! assert!(b.is_err());
34//! ```
35//!
36//! ```
37//! let a = ["1", "2", "3"];
38//! let b = array_util::try_map(a, |v| v.parse::<u32>()).unwrap().map(|v| v + 1);
39//! assert_eq!(b, [2, 3, 4]);
40//!
41//! let a = ["1", "2a", "3"];
42//! let b = array_util::try_map(a, |v| v.parse::<u32>());
43//! assert!(b.is_err());
44//! ```
45//!
46//! ## Limitations
47//!
48//! These functions aren't stabilized because they rely on undecided behaviors.
49//! For example, "should compile-time errors be generated for `0` length
50//! arrays?" or "What should the associated types and traits of `Try` be?". As
51//! these questions remain unresolved, reliance on the particular answers
52//! this crate has chosen in it's implementation may make porting to the
53//! eventual stabilized version more painful. If you're just calling functions,
54//! you'll probably be fine, but try to avoid using the `Ext` traits as bounds.
55//!  
56//! [`array_try_from_fn`]: https://github.com/rust-lang/rust/issues/89379
57//! [`array_try_map`]: https://github.com/rust-lang/rust/issues/79711
58//! [`array_chunks`]: https://github.com/rust-lang/rust/issues/74985
59//! [`slice_as_chunks`]: https://github.com/rust-lang/rust/issues/74985
60//! [`slice_flatten`]: https://github.com/rust-lang/rust/issues/95629
61#![no_std]
62#![warn(missing_docs)]
63
64use core::{array, iter::FusedIterator, mem::size_of, ops::ControlFlow, slice};
65
66use arrayvec::ArrayVec;
67
68#[doc(hidden)]
69mod try_helper;
70
71use try_helper::*;
72
73/// A fallible function `f` applied to each element on array `self` in order to
74/// return an array the same size as `self` or the first error encountered.
75///
76/// The return type of this function depends on the return type of the closure.
77/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
78/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
79///
80/// # Examples
81///
82/// ```
83/// let a = ["1", "2", "3"];
84/// let b = array_util::try_map(a, |v| v.parse::<u32>()).unwrap().map(|v| v + 1);
85/// assert_eq!(b, [2, 3, 4]);
86///
87/// let a = ["1", "2a", "3"];
88/// let b = array_util::try_map(a, |v| v.parse::<u32>());
89/// assert!(b.is_err());
90///
91/// use std::num::NonZeroU32;
92/// let z = [1, 2, 0, 3, 4];
93/// assert_eq!(array_util::try_map(z, NonZeroU32::new), None);
94/// let a = [1, 2, 3];
95/// let b = array_util::try_map(a, NonZeroU32::new);
96/// let c = b.map(|x| x.map(NonZeroU32::get));
97/// assert_eq!(c, Some(a));
98/// ```
99pub fn try_map<T, const N: usize, F, R>(
100    vals: [T; N],
101    mut f: F,
102) -> <<R as Try>::Residual as Residual<[<R as Try>::Output; N]>>::TryType
103where
104    F: FnMut(T) -> R,
105    R: Try,
106    <R as Try>::Residual: Residual<[<R as Try>::Output; N]>,
107{
108    let mut output = ArrayVec::new();
109    for val in vals {
110        match f(val).branch() {
111            ControlFlow::Break(b) => return FromResidual::from_residual(b),
112
113            // SAFETY: `val` is len N and `output` has capacity N
114            ControlFlow::Continue(c) => unsafe { output.push_unchecked(c) },
115        }
116    }
117    // SAFETY: `output` can only be len N if we got here
118    unsafe { Try::from_output(output.into_inner_unchecked()) }
119}
120
121/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
122/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
123/// if any element creation was unsuccessful.
124///
125/// The return type of this function depends on the return type of the closure.
126/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
127/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
128///
129/// # Arguments
130///
131/// * `cb`: Callback where the passed argument is the current array index.
132///
133/// # Example
134///
135/// ```rust
136/// # use core::convert::TryInto;
137/// let array: Result<[u8; 5], _> = array_util::try_from_fn(|i| i.try_into());
138/// assert_eq!(array, Ok([0, 1, 2, 3, 4]));
139///
140/// let array: Result<[i8; 200], _> = array_util::try_from_fn(|i| i.try_into());
141/// assert!(array.is_err());
142///
143/// let array: Option<[_; 4]> = array_util::try_from_fn(|i| i.checked_add(100));
144/// assert_eq!(array, Some([100, 101, 102, 103]));
145///
146/// let array: Option<[_; 4]> = array_util::try_from_fn(|i| i.checked_sub(100));
147/// assert_eq!(array, None);
148/// ```
149///
150/// [`from_fn`]: core::array::from_fn
151#[inline]
152pub fn try_from_fn<R, const N: usize, F>(
153    cb: F,
154) -> <<R as Try>::Residual as Residual<[R::Output; N]>>::TryType
155where
156    F: FnMut(usize) -> R,
157    R: Try,
158    R::Residual: Residual<[R::Output; N]>,
159{
160    try_map(array::from_fn(|i| i), cb)
161}
162
163/// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
164/// time), starting at the beginning of the slice.
165///
166/// When the slice len is not evenly divided by the chunk size, the last
167/// up to `N-1` elements will be omitted but can be retrieved from
168/// the [`remainder`] function from the iterator.
169///
170/// This struct is created by the [`array_chunks`] method on [slices].
171///
172/// # Example
173///
174/// ```
175/// let slice = ['l', 'o', 'r', 'e', 'm'];
176/// let iter = array_util::array_chunks::<_, 2>(&slice);
177/// ```
178///
179/// [`remainder`]: ArrayChunks::remainder
180/// [slices]: prim@slice
181#[derive(Debug)]
182#[must_use = "iterators are lazy and do nothing unless consumed"]
183pub struct ArrayChunks<'a, T: 'a, const N: usize> {
184    iter: slice::Iter<'a, [T; N]>,
185    rem: &'a [T],
186}
187
188impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
189    #[inline]
190    pub(crate) fn new(slice: &'a [T]) -> Self {
191        let (array_slice, rem) = as_chunks(slice);
192        Self {
193            iter: array_slice.iter(),
194            rem,
195        }
196    }
197
198    /// Returns the remainder of the original slice that is not going to be
199    /// returned by the iterator. The returned slice has at most `N-1`
200    /// elements.
201    #[must_use]
202    pub fn remainder(&self) -> &'a [T] {
203        self.rem
204    }
205}
206
207impl<T, const N: usize> Clone for ArrayChunks<'_, T, N> {
208    fn clone(&self) -> Self {
209        ArrayChunks {
210            iter: self.iter.clone(),
211            rem: self.rem,
212        }
213    }
214}
215
216impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> {
217    type Item = &'a [T; N];
218
219    #[inline]
220    fn next(&mut self) -> Option<&'a [T; N]> {
221        self.iter.next()
222    }
223
224    #[inline]
225    fn size_hint(&self) -> (usize, Option<usize>) {
226        self.iter.size_hint()
227    }
228
229    #[inline]
230    fn count(self) -> usize {
231        self.iter.count()
232    }
233
234    #[inline]
235    fn nth(&mut self, n: usize) -> Option<Self::Item> {
236        self.iter.nth(n)
237    }
238
239    #[inline]
240    fn last(self) -> Option<Self::Item> {
241        self.iter.last()
242    }
243}
244
245impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> {
246    #[inline]
247    fn next_back(&mut self) -> Option<&'a [T; N]> {
248        self.iter.next_back()
249    }
250
251    #[inline]
252    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
253        self.iter.nth_back(n)
254    }
255}
256
257impl<T, const N: usize> ExactSizeIterator for ArrayChunks<'_, T, N> {}
258
259impl<T, const N: usize> FusedIterator for ArrayChunks<'_, T, N> {}
260
261/// Returns an iterator over `N` elements of the slice at a time, starting at the
262/// beginning of the slice.
263///
264/// The chunks are array references and do not overlap. If `N` does not divide the
265/// length of the slice, then the last up to `N-1` elements will be omitted and can be
266/// retrieved from the `remainder` function of the iterator.
267///
268/// This method is the const generic equivalent of [`chunks_exact`].
269///
270/// # Panics
271///
272/// Panics if `N` is 0. This check will most probably get changed to a compile time
273/// error before this method gets stabilized.
274///
275/// # Examples
276///
277/// ```
278/// let slice = ['l', 'o', 'r', 'e', 'm'];
279/// let mut iter = array_util::array_chunks(&slice);
280/// assert_eq!(iter.next().unwrap(), &['l', 'o']);
281/// assert_eq!(iter.next().unwrap(), &['r', 'e']);
282/// assert!(iter.next().is_none());
283/// assert_eq!(iter.remainder(), &['m']);
284/// ```
285///
286/// [`chunks_exact`]: prim@slice#method.chunks_exact
287#[inline]
288pub fn array_chunks<T, const N: usize>(vals: &[T]) -> ArrayChunks<'_, T, N> {
289    assert!(N != 0, "chunk size must be non-zero");
290    ArrayChunks::new(vals)
291}
292
293/// An iterator over a slice in (non-overlapping) mutable chunks (`N` elements
294/// at a time), starting at the beginning of the slice.
295///
296/// When the slice len is not evenly divided by the chunk size, the last
297/// up to `N-1` elements will be omitted but can be retrieved from
298/// the [`into_remainder`] function from the iterator.
299///
300/// This struct is created by the [`array_chunks_mut`] method on [slices].
301///
302/// # Example
303///
304/// ```
305/// let mut slice = ['l', 'o', 'r', 'e', 'm'];
306/// let iter = array_util::array_chunks_mut::<_, 2>(&mut slice);
307/// ```
308///
309/// [`into_remainder`]: ArrayChunksMut::into_remainder
310/// [slices]: prim@slice
311#[derive(Debug)]
312#[must_use = "iterators are lazy and do nothing unless consumed"]
313pub struct ArrayChunksMut<'a, T: 'a, const N: usize> {
314    iter: slice::IterMut<'a, [T; N]>,
315    rem: &'a mut [T],
316}
317
318impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> {
319    #[inline]
320    pub(crate) fn new(slice: &'a mut [T]) -> Self {
321        let (array_slice, rem) = as_chunks_mut(slice);
322        Self {
323            iter: array_slice.iter_mut(),
324            rem,
325        }
326    }
327
328    /// Returns the remainder of the original slice that is not going to be
329    /// returned by the iterator. The returned slice has at most `N-1`
330    /// elements.
331    #[must_use]
332    pub fn into_remainder(self) -> &'a mut [T] {
333        self.rem
334    }
335}
336
337impl<'a, T, const N: usize> Iterator for ArrayChunksMut<'a, T, N> {
338    type Item = &'a mut [T; N];
339
340    #[inline]
341    fn next(&mut self) -> Option<&'a mut [T; N]> {
342        self.iter.next()
343    }
344
345    #[inline]
346    fn size_hint(&self) -> (usize, Option<usize>) {
347        self.iter.size_hint()
348    }
349
350    #[inline]
351    fn count(self) -> usize {
352        self.iter.count()
353    }
354
355    #[inline]
356    fn nth(&mut self, n: usize) -> Option<Self::Item> {
357        self.iter.nth(n)
358    }
359
360    #[inline]
361    fn last(self) -> Option<Self::Item> {
362        self.iter.last()
363    }
364}
365
366impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunksMut<'a, T, N> {
367    #[inline]
368    fn next_back(&mut self) -> Option<&'a mut [T; N]> {
369        self.iter.next_back()
370    }
371
372    #[inline]
373    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
374        self.iter.nth_back(n)
375    }
376}
377
378impl<T, const N: usize> ExactSizeIterator for ArrayChunksMut<'_, T, N> {}
379
380impl<T, const N: usize> FusedIterator for ArrayChunksMut<'_, T, N> {}
381
382/// Returns an iterator over `N` elements of the slice at a time, starting at the
383/// beginning of the slice.
384///
385/// The chunks are mutable array references and do not overlap. If `N` does not divide
386/// the length of the slice, then the last up to `N-1` elements will be omitted and
387/// can be retrieved from the `into_remainder` function of the iterator.
388///
389/// This method is the const generic equivalent of [`chunks_exact_mut`].
390///
391/// # Panics
392///
393/// Panics if `N` is 0. This check will most probably get changed to a compile time
394/// error before this method gets stabilized.
395///
396/// # Examples
397///
398/// ```
399/// let v = &mut [0, 0, 0, 0, 0];
400/// let mut count = 1;
401///
402/// for chunk in array_util::array_chunks_mut(v) {
403///     *chunk = [count; 2];
404///     count += 1;
405/// }
406/// assert_eq!(v, &[1, 1, 2, 2, 0]);
407/// ```
408///
409/// [`chunks_exact_mut`]: prim@slice#method.chunks_exact_mut
410#[inline]
411pub fn array_chunks_mut<T, const N: usize>(vals: &mut [T]) -> ArrayChunksMut<'_, T, N> {
412    assert!(N != 0, "chunk size must be non-zero");
413    ArrayChunksMut::new(vals)
414}
415
416/// Splits the slice into a slice of `N`-element arrays,
417/// starting at the beginning of the slice,
418/// and a remainder slice with length strictly less than `N`.
419///
420/// # Panics
421///
422/// Panics if `N` is 0. This check will most probably get changed to a compile time
423/// error before this method gets stabilized.
424///
425/// # Examples
426///
427/// ```
428/// let slice = ['l', 'o', 'r', 'e', 'm'];
429/// let (chunks, remainder) = array_util::as_chunks(&slice);
430/// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
431/// assert_eq!(remainder, &['m']);
432/// ```
433///
434/// If you expect the slice to be an exact multiple, you can combine
435/// `let`-`else` with an empty slice pattern:
436/// ```
437/// let slice = ['R', 'u', 's', 't'];
438/// let (chunks, []) = array_util::as_chunks::<_, 2>(&slice) else {
439///     panic!("slice didn't have even length")
440/// };
441/// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
442/// ```
443#[inline]
444#[must_use]
445pub const fn as_chunks<T, const N: usize>(vals: &[T]) -> (&[[T; N]], &[T]) {
446    assert!(N != 0, "chunk size must be non-zero");
447    let len = vals.len() / N;
448    let (multiple_of_n, remainder) = vals.split_at(len * N);
449    // SAFETY: We already panicked for zero, and ensured by construction
450    // that the length of the subslice is a multiple of N.
451    let array_slice = unsafe { as_chunks_unchecked(multiple_of_n) };
452    (array_slice, remainder)
453}
454
455/// Splits the slice into a slice of `N`-element arrays,
456/// assuming that there's no remainder.
457///
458/// # Safety
459///
460/// This may only be called when
461/// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
462/// - `N != 0`.
463///
464/// # Examples
465///
466/// ```
467/// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
468/// let chunks: &[[char; 1]] =
469///     // SAFETY: 1-element chunks never have remainder
470///     unsafe { array_util::as_chunks_unchecked(&slice) };
471/// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
472/// let chunks: &[[char; 3]] =
473///     // SAFETY: The slice length (6) is a multiple of 3
474///     unsafe { array_util::as_chunks_unchecked(&slice) };
475/// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
476///
477/// // These would be unsound:
478/// // let chunks: &[[_; 5]] = array_util::as_chunks_unchecked(slice) // The slice length is not a multiple of 5
479/// // let chunks: &[[_; 0]] = array_util::as_chunks_unchecked(slice) // Zero-length chunks are never allowed
480/// ```
481#[inline]
482#[must_use]
483pub const unsafe fn as_chunks_unchecked<T, const N: usize>(vals: &[T]) -> &[[T; N]] {
484    debug_assert!(
485        N != 0 && vals.len() % N == 0,
486        "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks",
487    );
488    let new_len = vals.len() / N;
489    // SAFETY: We cast a slice of `new_len * N` elements into
490    // a slice of `new_len` many `N` elements chunks.
491    unsafe { slice::from_raw_parts(vals.as_ptr().cast(), new_len) }
492}
493
494/// Splits the slice into a slice of `N`-element arrays,
495/// starting at the beginning of the slice,
496/// and a remainder slice with length strictly less than `N`.
497///
498/// # Panics
499///
500/// Panics if `N` is 0. This check will most probably get changed to a compile time
501/// error before this method gets stabilized.
502///
503/// # Examples
504///
505/// ```
506/// let v = &mut [0, 0, 0, 0, 0];
507/// let mut count = 1;
508///
509/// let (chunks, remainder) = array_util::as_chunks_mut(v);
510/// remainder[0] = 9;
511/// for chunk in chunks {
512///     *chunk = [count; 2];
513///     count += 1;
514/// }
515/// assert_eq!(v, &[1, 1, 2, 2, 9]);
516/// ```
517#[inline]
518#[must_use]
519pub fn as_chunks_mut<T, const N: usize>(vals: &mut [T]) -> (&mut [[T; N]], &mut [T]) {
520    assert!(N != 0, "chunk size must be non-zero");
521    let len = vals.len() / N;
522    let (multiple_of_n, remainder) = vals.split_at_mut(len * N);
523    // SAFETY: We already panicked for zero, and ensured by construction
524    // that the length of the subslice is a multiple of N.
525    let array_slice = unsafe { as_chunks_unchecked_mut(multiple_of_n) };
526    (array_slice, remainder)
527}
528
529/// Splits the slice into a slice of `N`-element arrays,
530/// assuming that there's no remainder.
531///
532/// # Safety
533///
534/// This may only be called when
535/// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
536/// - `N != 0`.
537///
538/// # Examples
539///
540/// ```
541/// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
542/// let chunks: &mut [[char; 1]] =
543///     // SAFETY: 1-element chunks never have remainder
544///     unsafe { array_util::as_chunks_unchecked_mut(slice) };
545/// chunks[0] = ['L'];
546/// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
547/// let chunks: &mut [[char; 3]] =
548///     // SAFETY: The slice length (6) is a multiple of 3
549///     unsafe { array_util::as_chunks_unchecked_mut(slice) };
550/// chunks[1] = ['a', 'x', '?'];
551/// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
552///
553/// // These would be unsound:
554/// // let chunks: &[[_; 5]] = array_util::as_chunks_unchecked_mut(slice) // The slice length is not a multiple of 5
555/// // let chunks: &[[_; 0]] = array_util::as_chunks_unchecked_mut(slice) // Zero-length chunks are never allowed
556/// ```
557#[inline]
558#[must_use]
559pub unsafe fn as_chunks_unchecked_mut<T, const N: usize>(vals: &mut [T]) -> &mut [[T; N]] {
560    debug_assert!(
561        N != 0 && vals.len() % N == 0,
562        "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks",
563    );
564    let new_len = vals.len() / N;
565    // SAFETY: We cast a slice of `new_len * N` elements into
566    // a slice of `new_len` many `N` elements chunks.
567    unsafe { slice::from_raw_parts_mut(vals.as_mut_ptr().cast(), new_len) }
568}
569
570/// Splits the slice into a slice of `N`-element arrays,
571/// starting at the end of the slice,
572/// and a remainder slice with length strictly less than `N`.
573///
574/// # Panics
575///
576/// Panics if `N` is 0. This check will most probably get changed to a compile time
577/// error before this method gets stabilized.
578///
579/// # Examples
580///
581/// ```
582/// let slice = ['l', 'o', 'r', 'e', 'm'];
583/// let (remainder, chunks) = array_util::as_rchunks(&slice);
584/// assert_eq!(remainder, &['l']);
585/// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
586/// ```
587#[inline]
588#[must_use]
589pub const fn as_rchunks<T, const N: usize>(vals: &[T]) -> (&[T], &[[T; N]]) {
590    assert!(N != 0, "chunk size must be non-zero");
591    let len = vals.len() / N;
592    let (remainder, multiple_of_n) = vals.split_at(vals.len() - len * N);
593    // SAFETY: We already panicked for zero, and ensured by construction
594    // that the length of the subslice is a multiple of N.
595    let array_slice = unsafe { as_chunks_unchecked(multiple_of_n) };
596    (remainder, array_slice)
597}
598
599/// Splits the slice into a slice of `N`-element arrays,
600/// starting at the end of the slice,
601/// and a remainder slice with length strictly less than `N`.
602///
603/// # Panics
604///
605/// Panics if `N` is 0. This check will most probably get changed to a compile time
606/// error before this method gets stabilized.
607///
608/// # Examples
609///
610/// ```
611/// let v = &mut [0, 0, 0, 0, 0];
612/// let mut count = 1;
613///
614/// let (remainder, chunks) = array_util::as_rchunks_mut(v);
615/// remainder[0] = 9;
616/// for chunk in chunks {
617///     *chunk = [count; 2];
618///     count += 1;
619/// }
620/// assert_eq!(v, &[9, 1, 1, 2, 2]);
621/// ```
622#[inline]
623#[must_use]
624pub fn as_rchunks_mut<T, const N: usize>(vals: &mut [T]) -> (&mut [T], &mut [[T; N]]) {
625    assert!(N != 0, "chunk size must be non-zero");
626    let len = vals.len() / N;
627    let (remainder, multiple_of_n) = vals.split_at_mut(vals.len() - len * N);
628    // SAFETY: We already panicked for zero, and ensured by construction
629    // that the length of the subslice is a multiple of N.
630    let array_slice = unsafe { as_chunks_unchecked_mut(multiple_of_n) };
631    (remainder, array_slice)
632}
633
634/// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
635///
636/// # Panics
637///
638/// This panics if the length of the resulting slice would overflow a `usize`.
639///
640/// This is only possible when flattening a slice of arrays of zero-sized
641/// types, and thus tends to be irrelevant in practice. If
642/// `size_of::<T>() > 0`, this will never panic.
643///
644/// # Examples
645///
646/// ```
647/// assert_eq!(array_util::flatten(&[[1, 2, 3], [4, 5, 6]]), &[1, 2, 3, 4, 5, 6]);
648///
649/// assert_eq!(
650///     array_util::flatten(&[[1, 2, 3], [4, 5, 6]]),
651///     array_util::flatten(&[[1, 2], [3, 4], [5, 6]]),
652/// );
653///
654/// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
655/// assert!(array_util::flatten(&slice_of_empty_arrays).is_empty());
656///
657/// let empty_slice_of_arrays: &[[u32; 10]] = &[];
658/// assert!(array_util::flatten(&empty_slice_of_arrays).is_empty());
659/// ```
660pub const fn flatten<T, const N: usize>(vals: &[[T; N]]) -> &[T] {
661    let len = if size_of::<T>() == 0 {
662        match vals.len().checked_mul(N) {
663            Some(v) => v,
664            None => panic!("slice len overflow"),
665        }
666    } else {
667        vals.len() * N
668    };
669    // SAFETY: `[T]` is layout-identical to `[T; N]`
670    unsafe { slice::from_raw_parts(vals.as_ptr().cast(), len) }
671}
672
673/// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`.
674///
675/// # Panics
676///
677/// This panics if the length of the resulting slice would overflow a `usize`.
678///
679/// This is only possible when flattening a slice of arrays of zero-sized
680/// types, and thus tends to be irrelevant in practice. If
681/// `size_of::<T>() > 0`, this will never panic.
682///
683/// # Examples
684///
685/// ```
686/// fn add_5_to_all(slice: &mut [i32]) {
687///     for i in slice {
688///         *i += 5;
689///     }
690/// }
691///
692/// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
693/// add_5_to_all(array_util::flatten_mut(&mut array));
694/// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
695/// ```
696pub fn flatten_mut<T, const N: usize>(vals: &mut [[T; N]]) -> &mut [T] {
697    let len = if size_of::<T>() == 0 {
698        vals.len().checked_mul(N).expect("slice len overflow")
699    } else {
700        vals.len() * N
701    };
702    // SAFETY: `[T]` is layout-identical to `[T; N]`
703    unsafe { slice::from_raw_parts_mut(vals.as_mut_ptr().cast(), len) }
704}
705
706/// A helper extension trait for arrays
707pub trait ArrayExt {
708    #[doc(hidden)]
709    type T;
710    #[doc(hidden)]
711    type TN<U>: ArrayExt<T = U, TN<Self::T> = Self>;
712
713    /// A fallible function `f` applied to each element on array `self` in order to
714    /// return an array the same size as `self` or the first error encountered.
715    ///
716    /// The return type of this function depends on the return type of the closure.
717    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
718    /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
719    ///
720    /// # Examples
721    ///
722    /// ```
723    /// use array_util::ArrayExt;
724    ///
725    /// let a = ["1", "2", "3"];
726    /// let b = a.try_map_ext(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
727    /// assert_eq!(b, [2, 3, 4]);
728    ///
729    /// let a = ["1", "2a", "3"];
730    /// let b = a.try_map_ext(|v| v.parse::<u32>());
731    /// assert!(b.is_err());
732    ///
733    /// use std::num::NonZeroU32;
734    /// let z = [1, 2, 0, 3, 4];
735    /// assert_eq!(z.try_map_ext(NonZeroU32::new), None);
736    /// let a = [1, 2, 3];
737    /// let b = a.try_map_ext(NonZeroU32::new);
738    /// let c = b.map(|x| x.map(NonZeroU32::get));
739    /// assert_eq!(c, Some(a));
740    /// ```
741    fn try_map_ext<F, R>(
742        self,
743        f: F,
744    ) -> <<R as Try>::Residual as Residual<Self::TN<<R as Try>::Output>>>::TryType
745    where
746        F: FnMut(Self::T) -> R,
747        R: Try,
748        <R as Try>::Residual: Residual<Self::TN<<R as Try>::Output>>;
749}
750
751impl<T, const N: usize> ArrayExt for [T; N] {
752    type T = T;
753    type TN<U> = [U; N];
754
755    /// A fallible function `f` applied to each element on array `self` in order to
756    /// return an array the same size as `self` or the first error encountered.
757    ///
758    /// The return type of this function depends on the return type of the closure.
759    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
760    /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
761    ///
762    /// # Examples
763    ///
764    /// ```
765    /// use array_util::ArrayExt;
766    ///
767    /// let a = ["1", "2", "3"];
768    /// let b = a.try_map_ext(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
769    /// assert_eq!(b, [2, 3, 4]);
770    ///
771    /// let a = ["1", "2a", "3"];
772    /// let b = a.try_map_ext(|v| v.parse::<u32>());
773    /// assert!(b.is_err());
774    ///
775    /// use std::num::NonZeroU32;
776    /// let z = [1, 2, 0, 3, 4];
777    /// assert_eq!(z.try_map_ext(NonZeroU32::new), None);
778    /// let a = [1, 2, 3];
779    /// let b = a.try_map_ext(NonZeroU32::new);
780    /// let c = b.map(|x| x.map(NonZeroU32::get));
781    /// assert_eq!(c, Some(a));
782    /// ```
783    #[inline]
784    fn try_map_ext<F, R>(
785        self,
786        f: F,
787    ) -> <<R as Try>::Residual as Residual<[<R as Try>::Output; N]>>::TryType
788    where
789        F: FnMut(T) -> R,
790        R: Try,
791        <R as Try>::Residual: Residual<[<R as Try>::Output; N]>,
792    {
793        try_map(self, f)
794    }
795}
796
797/// A helper extension trait for slices
798pub trait SliceExt {
799    #[doc(hidden)]
800    type T;
801
802    /// Returns an iterator over `N` elements of the slice at a time, starting at the
803    /// beginning of the slice.
804    ///
805    /// The chunks are array references and do not overlap. If `N` does not divide the
806    /// length of the slice, then the last up to `N-1` elements will be omitted and can be
807    /// retrieved from the `remainder` function of the iterator.
808    ///
809    /// This method is the const generic equivalent of [`chunks_exact`].
810    ///
811    /// # Panics
812    ///
813    /// Panics if `N` is 0. This check will most probably get changed to a compile time
814    /// error before this method gets stabilized.
815    ///
816    /// # Examples
817    ///
818    /// ```
819    /// use array_util::SliceExt;
820    ///
821    /// let slice = ['l', 'o', 'r', 'e', 'm'];
822    /// let mut iter = slice.array_chunks_ext();
823    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
824    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
825    /// assert!(iter.next().is_none());
826    /// assert_eq!(iter.remainder(), &['m']);
827    /// ```
828    ///
829    /// [`chunks_exact`]: prim@slice#method.chunks_exact
830    fn array_chunks_ext<const N: usize>(&self) -> ArrayChunks<'_, Self::T, N>;
831
832    /// Returns an iterator over `N` elements of the slice at a time, starting at the
833    /// beginning of the slice.
834    ///
835    /// The chunks are mutable array references and do not overlap. If `N` does not divide
836    /// the length of the slice, then the last up to `N-1` elements will be omitted and
837    /// can be retrieved from the `into_remainder` function of the iterator.
838    ///
839    /// This method is the const generic equivalent of [`chunks_exact_mut`].
840    ///
841    /// # Panics
842    ///
843    /// Panics if `N` is 0. This check will most probably get changed to a compile time
844    /// error before this method gets stabilized.
845    ///
846    /// # Examples
847    ///
848    /// ```
849    /// use array_util::SliceExt;
850    ///
851    /// let v = &mut [0, 0, 0, 0, 0];
852    /// let mut count = 1;
853    ///
854    /// for chunk in v.array_chunks_mut_ext() {
855    ///     *chunk = [count; 2];
856    ///     count += 1;
857    /// }
858    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
859    /// ```
860    ///
861    /// [`chunks_exact_mut`]: prim@slice#method.chunks_exact_mut
862    fn array_chunks_mut_ext<const N: usize>(&mut self) -> ArrayChunksMut<'_, Self::T, N>;
863
864    /// Splits the slice into a slice of `N`-element arrays,
865    /// starting at the beginning of the slice,
866    /// and a remainder slice with length strictly less than `N`.
867    ///
868    /// # Panics
869    ///
870    /// Panics if `N` is 0. This check will most probably get changed to a compile time
871    /// error before this method gets stabilized.
872    ///
873    /// # Examples
874    ///
875    /// ```
876    /// use array_util::SliceExt;
877    ///
878    /// let slice = ['l', 'o', 'r', 'e', 'm'];
879    /// let (chunks, remainder) = slice.as_chunks_ext();
880    /// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
881    /// assert_eq!(remainder, &['m']);
882    /// ```
883    ///
884    /// If you expect the slice to be an exact multiple, you can combine
885    /// `let`-`else` with an empty slice pattern:
886    /// ```
887    /// use array_util::SliceExt;
888    ///
889    /// let slice = ['R', 'u', 's', 't'];
890    /// let (chunks, []) = slice.as_chunks_ext::<2>() else {
891    ///     panic!("slice didn't have even length")
892    /// };
893    /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
894    /// ```
895    #[must_use]
896    fn as_chunks_ext<const N: usize>(&self) -> (&[[Self::T; N]], &[Self::T]);
897
898    /// Splits the slice into a slice of `N`-element arrays,
899    /// assuming that there's no remainder.
900    ///
901    /// # Safety
902    ///
903    /// This may only be called when
904    /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
905    /// - `N != 0`.
906    ///
907    /// # Examples
908    ///
909    /// ```
910    /// use array_util::SliceExt;
911    ///
912    /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
913    /// let chunks: &[[char; 1]] =
914    ///     // SAFETY: 1-element chunks never have remainder
915    ///     unsafe { slice.as_chunks_unchecked_ext() };
916    /// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
917    /// let chunks: &[[char; 3]] =
918    ///     // SAFETY: The slice length (6) is a multiple of 3
919    ///     unsafe { slice.as_chunks_unchecked_ext() };
920    /// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
921    ///
922    /// // These would be unsound:
923    /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_ext() // The slice length is not a multiple of 5
924    /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_ext() // Zero-length chunks are never allowed
925    /// ```
926    #[must_use]
927    unsafe fn as_chunks_unchecked_ext<const N: usize>(&self) -> &[[Self::T; N]];
928
929    /// Splits the slice into a slice of `N`-element arrays,
930    /// starting at the beginning of the slice,
931    /// and a remainder slice with length strictly less than `N`.
932    ///
933    /// # Panics
934    ///
935    /// Panics if `N` is 0. This check will most probably get changed to a compile time
936    /// error before this method gets stabilized.
937    ///
938    /// # Examples
939    ///
940    /// ```
941    /// use array_util::SliceExt;
942    ///
943    /// let v = &mut [0, 0, 0, 0, 0];
944    /// let mut count = 1;
945    ///
946    /// let (chunks, remainder) = v.as_chunks_mut_ext();
947    /// remainder[0] = 9;
948    /// for chunk in chunks {
949    ///     *chunk = [count; 2];
950    ///     count += 1;
951    /// }
952    /// assert_eq!(v, &[1, 1, 2, 2, 9]);
953    /// ```
954    #[must_use]
955    fn as_chunks_mut_ext<const N: usize>(&mut self) -> (&mut [[Self::T; N]], &mut [Self::T]);
956
957    /// Splits the slice into a slice of `N`-element arrays,
958    /// assuming that there's no remainder.
959    ///
960    /// # Safety
961    ///
962    /// This may only be called when
963    /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
964    /// - `N != 0`.
965    ///
966    /// # Examples
967    ///
968    /// ```
969    /// use array_util::SliceExt;
970    ///
971    /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
972    /// let chunks: &mut [[char; 1]] =
973    ///     // SAFETY: 1-element chunks never have remainder
974    ///     unsafe { slice.as_chunks_unchecked_mut_ext() };
975    /// chunks[0] = ['L'];
976    /// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
977    /// let chunks: &mut [[char; 3]] =
978    ///     // SAFETY: The slice length (6) is a multiple of 3
979    ///     unsafe { slice.as_chunks_unchecked_mut_ext() };
980    /// chunks[1] = ['a', 'x', '?'];
981    /// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
982    ///
983    /// // These would be unsound:
984    /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut_ext() // The slice length is not a multiple of 5
985    /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut_ext() // Zero-length chunks are never allowed
986    /// ```
987    #[must_use]
988    unsafe fn as_chunks_unchecked_mut_ext<const N: usize>(&mut self) -> &mut [[Self::T; N]];
989
990    /// Splits the slice into a slice of `N`-element arrays,
991    /// starting at the end of the slice,
992    /// and a remainder slice with length strictly less than `N`.
993    ///
994    /// # Panics
995    ///
996    /// Panics if `N` is 0. This check will most probably get changed to a compile time
997    /// error before this method gets stabilized.
998    ///
999    /// # Examples
1000    ///
1001    /// ```
1002    /// use array_util::SliceExt;
1003    ///
1004    /// let slice = ['l', 'o', 'r', 'e', 'm'];
1005    /// let (remainder, chunks) = slice.as_rchunks_ext();
1006    /// assert_eq!(remainder, &['l']);
1007    /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
1008    /// ```
1009    #[must_use]
1010
1011    fn as_rchunks_ext<const N: usize>(&self) -> (&[Self::T], &[[Self::T; N]]);
1012    /// Splits the slice into a slice of `N`-element arrays,
1013    /// starting at the end of the slice,
1014    /// and a remainder slice with length strictly less than `N`.
1015    ///
1016    /// # Panics
1017    ///
1018    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1019    /// error before this method gets stabilized.
1020    ///
1021    /// # Examples
1022    ///
1023    /// ```
1024    /// use array_util::SliceExt;
1025    ///
1026    /// let v = &mut [0, 0, 0, 0, 0];
1027    /// let mut count = 1;
1028    ///
1029    /// let (remainder, chunks) = v.as_rchunks_mut_ext();
1030    /// remainder[0] = 9;
1031    /// for chunk in chunks {
1032    ///     *chunk = [count; 2];
1033    ///     count += 1;
1034    /// }
1035    /// assert_eq!(v, &[9, 1, 1, 2, 2]);
1036    /// ```
1037    #[must_use]
1038    fn as_rchunks_mut_ext<const N: usize>(&mut self) -> (&mut [Self::T], &mut [[Self::T; N]]);
1039}
1040
1041impl<T> SliceExt for [T] {
1042    type T = T;
1043
1044    /// Returns an iterator over `N` elements of the slice at a time, starting at the
1045    /// beginning of the slice.
1046    ///
1047    /// The chunks are array references and do not overlap. If `N` does not divide the
1048    /// length of the slice, then the last up to `N-1` elements will be omitted and can be
1049    /// retrieved from the `remainder` function of the iterator.
1050    ///
1051    /// This method is the const generic equivalent of [`chunks_exact`].
1052    ///
1053    /// # Panics
1054    ///
1055    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1056    /// error before this method gets stabilized.
1057    ///
1058    /// # Examples
1059    ///
1060    /// ```
1061    /// use array_util::SliceExt;
1062    ///
1063    /// let slice = ['l', 'o', 'r', 'e', 'm'];
1064    /// let mut iter = slice.array_chunks_ext();
1065    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
1066    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
1067    /// assert!(iter.next().is_none());
1068    /// assert_eq!(iter.remainder(), &['m']);
1069    /// ```
1070    ///
1071    /// [`chunks_exact`]: prim@slice#method.chunks_exact
1072    #[inline]
1073    fn array_chunks_ext<const N: usize>(&self) -> ArrayChunks<'_, Self::T, N> {
1074        array_chunks(self)
1075    }
1076
1077    /// Returns an iterator over `N` elements of the slice at a time, starting at the
1078    /// beginning of the slice.
1079    ///
1080    /// The chunks are mutable array references and do not overlap. If `N` does not divide
1081    /// the length of the slice, then the last up to `N-1` elements will be omitted and
1082    /// can be retrieved from the `into_remainder` function of the iterator.
1083    ///
1084    /// This method is the const generic equivalent of [`chunks_exact_mut`].
1085    ///
1086    /// # Panics
1087    ///
1088    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1089    /// error before this method gets stabilized.
1090    ///
1091    /// # Examples
1092    ///
1093    /// ```
1094    /// use array_util::SliceExt;
1095    ///
1096    /// let v = &mut [0, 0, 0, 0, 0];
1097    /// let mut count = 1;
1098    ///
1099    /// for chunk in v.array_chunks_mut_ext() {
1100    ///     *chunk = [count; 2];
1101    ///     count += 1;
1102    /// }
1103    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
1104    /// ```
1105    ///
1106    /// [`chunks_exact_mut`]: prim@slice#method.chunks_exact_mut
1107    #[inline]
1108    fn array_chunks_mut_ext<const N: usize>(&mut self) -> ArrayChunksMut<'_, Self::T, N> {
1109        array_chunks_mut(self)
1110    }
1111
1112    /// Splits the slice into a slice of `N`-element arrays,
1113    /// starting at the beginning of the slice,
1114    /// and a remainder slice with length strictly less than `N`.
1115    ///
1116    /// # Panics
1117    ///
1118    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1119    /// error before this method gets stabilized.
1120    ///
1121    /// # Examples
1122    ///
1123    /// ```
1124    /// use array_util::SliceExt;
1125    ///
1126    /// let slice = ['l', 'o', 'r', 'e', 'm'];
1127    /// let (chunks, remainder) = slice.as_chunks_ext();
1128    /// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
1129    /// assert_eq!(remainder, &['m']);
1130    /// ```
1131    ///
1132    /// If you expect the slice to be an exact multiple, you can combine
1133    /// `let`-`else` with an empty slice pattern:
1134    /// ```
1135    /// use array_util::SliceExt;
1136    ///
1137    /// let slice = ['R', 'u', 's', 't'];
1138    /// let (chunks, []) = slice.as_chunks_ext::<2>() else {
1139    ///     panic!("slice didn't have even length")
1140    /// };
1141    /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
1142    /// ```
1143    #[inline]
1144    #[must_use]
1145    fn as_chunks_ext<const N: usize>(&self) -> (&[[Self::T; N]], &[Self::T]) {
1146        as_chunks(self)
1147    }
1148
1149    /// Splits the slice into a slice of `N`-element arrays,
1150    /// assuming that there's no remainder.
1151    ///
1152    /// # Safety
1153    ///
1154    /// This may only be called when
1155    /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
1156    /// - `N != 0`.
1157    ///
1158    /// # Examples
1159    ///
1160    /// ```
1161    /// use array_util::SliceExt;
1162    ///
1163    /// let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
1164    /// let chunks: &[[char; 1]] =
1165    ///     // SAFETY: 1-element chunks never have remainder
1166    ///     unsafe { slice.as_chunks_unchecked_ext() };
1167    /// assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
1168    /// let chunks: &[[char; 3]] =
1169    ///     // SAFETY: The slice length (6) is a multiple of 3
1170    ///     unsafe { slice.as_chunks_unchecked_ext() };
1171    /// assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
1172    ///
1173    /// // These would be unsound:
1174    /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_ext() // The slice length is not a multiple of 5
1175    /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_ext() // Zero-length chunks are never allowed
1176    /// ```
1177    #[inline]
1178    #[must_use]
1179    unsafe fn as_chunks_unchecked_ext<const N: usize>(&self) -> &[[Self::T; N]] {
1180        as_chunks_unchecked(self)
1181    }
1182
1183    /// Splits the slice into a slice of `N`-element arrays,
1184    /// starting at the beginning of the slice,
1185    /// and a remainder slice with length strictly less than `N`.
1186    ///
1187    /// # Panics
1188    ///
1189    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1190    /// error before this method gets stabilized.
1191    ///
1192    /// # Examples
1193    ///
1194    /// ```
1195    /// use array_util::SliceExt;
1196    ///
1197    /// let v = &mut [0, 0, 0, 0, 0];
1198    /// let mut count = 1;
1199    ///
1200    /// let (chunks, remainder) = v.as_chunks_mut_ext();
1201    /// remainder[0] = 9;
1202    /// for chunk in chunks {
1203    ///     *chunk = [count; 2];
1204    ///     count += 1;
1205    /// }
1206    /// assert_eq!(v, &[1, 1, 2, 2, 9]);
1207    /// ```
1208    #[inline]
1209    #[must_use]
1210    fn as_chunks_mut_ext<const N: usize>(&mut self) -> (&mut [[Self::T; N]], &mut [Self::T]) {
1211        as_chunks_mut(self)
1212    }
1213
1214    /// Splits the slice into a slice of `N`-element arrays,
1215    /// assuming that there's no remainder.
1216    ///
1217    /// # Safety
1218    ///
1219    /// This may only be called when
1220    /// - The slice splits exactly into `N`-element chunks (aka `self.len() % N == 0`).
1221    /// - `N != 0`.
1222    ///
1223    /// # Examples
1224    ///
1225    /// ```
1226    /// use array_util::SliceExt;
1227    ///
1228    /// let slice: &mut [char] = &mut ['l', 'o', 'r', 'e', 'm', '!'];
1229    /// let chunks: &mut [[char; 1]] =
1230    ///     // SAFETY: 1-element chunks never have remainder
1231    ///     unsafe { slice.as_chunks_unchecked_mut_ext() };
1232    /// chunks[0] = ['L'];
1233    /// assert_eq!(chunks, &[['L'], ['o'], ['r'], ['e'], ['m'], ['!']]);
1234    /// let chunks: &mut [[char; 3]] =
1235    ///     // SAFETY: The slice length (6) is a multiple of 3
1236    ///     unsafe { slice.as_chunks_unchecked_mut_ext() };
1237    /// chunks[1] = ['a', 'x', '?'];
1238    /// assert_eq!(slice, &['L', 'o', 'r', 'a', 'x', '?']);
1239    ///
1240    /// // These would be unsound:
1241    /// // let chunks: &[[_; 5]] = slice.as_chunks_unchecked_mut_ext() // The slice length is not a multiple of 5
1242    /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut_ext() // Zero-length chunks are never allowed
1243    /// ```
1244    #[inline]
1245    #[must_use]
1246    unsafe fn as_chunks_unchecked_mut_ext<const N: usize>(&mut self) -> &mut [[Self::T; N]] {
1247        as_chunks_unchecked_mut(self)
1248    }
1249
1250    /// Splits the slice into a slice of `N`-element arrays,
1251    /// starting at the end of the slice,
1252    /// and a remainder slice with length strictly less than `N`.
1253    ///
1254    /// # Panics
1255    ///
1256    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1257    /// error before this method gets stabilized.
1258    ///
1259    /// # Examples
1260    ///
1261    /// ```
1262    /// use array_util::SliceExt;
1263    ///
1264    /// let slice = ['l', 'o', 'r', 'e', 'm'];
1265    /// let (remainder, chunks) = slice.as_rchunks_ext();
1266    /// assert_eq!(remainder, &['l']);
1267    /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
1268    /// ```
1269    #[inline]
1270    #[must_use]
1271    fn as_rchunks_ext<const N: usize>(&self) -> (&[Self::T], &[[Self::T; N]]) {
1272        as_rchunks(self)
1273    }
1274
1275    /// Splits the slice into a slice of `N`-element arrays,
1276    /// starting at the end of the slice,
1277    /// and a remainder slice with length strictly less than `N`.
1278    ///
1279    /// # Panics
1280    ///
1281    /// Panics if `N` is 0. This check will most probably get changed to a compile time
1282    /// error before this method gets stabilized.
1283    ///
1284    /// # Examples
1285    ///
1286    /// ```
1287    /// use array_util::SliceExt;
1288    ///
1289    /// let v = &mut [0, 0, 0, 0, 0];
1290    /// let mut count = 1;
1291    ///
1292    /// let (remainder, chunks) = v.as_rchunks_mut_ext();
1293    /// remainder[0] = 9;
1294    /// for chunk in chunks {
1295    ///     *chunk = [count; 2];
1296    ///     count += 1;
1297    /// }
1298    /// assert_eq!(v, &[9, 1, 1, 2, 2]);
1299    /// ```
1300    #[inline]
1301    #[must_use]
1302    fn as_rchunks_mut_ext<const N: usize>(&mut self) -> (&mut [Self::T], &mut [[Self::T; N]]) {
1303        as_rchunks_mut(self)
1304    }
1305}
1306
1307/// A helper extension trait for slices of arrays
1308pub trait SliceOfArrayExt {
1309    #[doc(hidden)]
1310    type T;
1311
1312    /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
1313    ///
1314    /// # Panics
1315    ///
1316    /// This panics if the length of the resulting slice would overflow a `usize`.
1317    ///
1318    /// This is only possible when flattening a slice of arrays of zero-sized
1319    /// types, and thus tends to be irrelevant in practice. If
1320    /// `size_of::<T>() > 0`, this will never panic.
1321    ///
1322    /// # Examples
1323    ///
1324    /// ```
1325    /// use array_util::SliceOfArrayExt;
1326    ///
1327    /// assert_eq!([[1, 2, 3], [4, 5, 6]].flatten_ext(), &[1, 2, 3, 4, 5, 6]);
1328    ///
1329    /// assert_eq!(
1330    ///     [[1, 2, 3], [4, 5, 6]].flatten_ext(),
1331    ///     [[1, 2], [3, 4], [5, 6]].flatten_ext(),
1332    /// );
1333    ///
1334    /// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
1335    /// assert!(slice_of_empty_arrays.flatten_ext().is_empty());
1336    ///
1337    /// let empty_slice_of_arrays: &[[u32; 10]] = &[];
1338    /// assert!(empty_slice_of_arrays.flatten_ext().is_empty());
1339    /// ```
1340    fn flatten_ext(&self) -> &[Self::T];
1341
1342    /// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`.
1343    ///
1344    /// # Panics
1345    ///
1346    /// This panics if the length of the resulting slice would overflow a `usize`.
1347    ///
1348    /// This is only possible when flattening a slice of arrays of zero-sized
1349    /// types, and thus tends to be irrelevant in practice. If
1350    /// `size_of::<T>() > 0`, this will never panic.
1351    ///
1352    /// # Examples
1353    ///
1354    /// ```
1355    /// use array_util::SliceOfArrayExt;
1356    ///
1357    /// fn add_5_to_all(slice: &mut [i32]) {
1358    ///     for i in slice {
1359    ///         *i += 5;
1360    ///     }
1361    /// }
1362    ///
1363    /// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
1364    /// add_5_to_all(array.flatten_mut_ext());
1365    /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
1366    /// ```
1367    fn flatten_mut_ext(&mut self) -> &mut [Self::T];
1368}
1369
1370impl<T, const N: usize> SliceOfArrayExt for [[T; N]] {
1371    type T = T;
1372
1373    /// Takes a `&[[T; N]]`, and flattens it to a `&[T]`.
1374    ///
1375    /// # Panics
1376    ///
1377    /// This panics if the length of the resulting slice would overflow a `usize`.
1378    ///
1379    /// This is only possible when flattening a slice of arrays of zero-sized
1380    /// types, and thus tends to be irrelevant in practice. If
1381    /// `size_of::<T>() > 0`, this will never panic.
1382    ///
1383    /// # Examples
1384    ///
1385    /// ```
1386    /// use array_util::SliceOfArrayExt;
1387    ///
1388    /// assert_eq!([[1, 2, 3], [4, 5, 6]].flatten_ext(), &[1, 2, 3, 4, 5, 6]);
1389    ///
1390    /// assert_eq!(
1391    ///     [[1, 2, 3], [4, 5, 6]].flatten_ext(),
1392    ///     [[1, 2], [3, 4], [5, 6]].flatten_ext(),
1393    /// );
1394    ///
1395    /// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
1396    /// assert!(slice_of_empty_arrays.flatten_ext().is_empty());
1397    ///
1398    /// let empty_slice_of_arrays: &[[u32; 10]] = &[];
1399    /// assert!(empty_slice_of_arrays.flatten_ext().is_empty());
1400    /// ```
1401    fn flatten_ext(&self) -> &[Self::T] {
1402        flatten(self)
1403    }
1404
1405    /// Takes a `&mut [[T; N]]`, and flattens it to a `&mut [T]`.
1406    ///
1407    /// # Panics
1408    ///
1409    /// This panics if the length of the resulting slice would overflow a `usize`.
1410    ///
1411    /// This is only possible when flattening a slice of arrays of zero-sized
1412    /// types, and thus tends to be irrelevant in practice. If
1413    /// `size_of::<T>() > 0`, this will never panic.
1414    ///
1415    /// # Examples
1416    ///
1417    /// ```
1418    /// use array_util::SliceOfArrayExt;
1419    ///
1420    /// fn add_5_to_all(slice: &mut [i32]) {
1421    ///     for i in slice {
1422    ///         *i += 5;
1423    ///     }
1424    /// }
1425    ///
1426    /// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
1427    /// add_5_to_all(array.flatten_mut_ext());
1428    /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
1429    /// ```
1430    fn flatten_mut_ext(&mut self) -> &mut [Self::T] {
1431        flatten_mut(self)
1432    }
1433}