generic_array/
lib.rs

1//! This crate implements a structure that can be used as a generic array type.
2//!
3//! **Requires minimum Rust version of 1.65.0
4//!
5//! [Documentation on GH Pages](https://fizyk20.github.io/generic-array/generic_array/)
6//! may be required to view certain types on foreign crates.
7//!
8//! Before Rust 1.51, arrays `[T; N]` were problematic in that they couldn't be
9//! generic with respect to the length `N`, so this wouldn't work:
10//!
11//! ```compile_fail
12//! struct Foo<N> {
13//!     data: [i32; N],
14//! }
15//! ```
16//!
17//! Since 1.51, the below syntax is valid:
18//!
19//! ```rust
20//! struct Foo<const N: usize> {
21//!     data: [i32; N],
22//! }
23//! ```
24//!
25//! However, the const-generics we have as of writing this are still the minimum-viable product (`min_const_generics`), so many situations still result in errors, such as this example:
26//!
27//! ```compile_fail
28//! # struct Foo<const N: usize> {
29//! #   data: [i32; N],
30//! # }
31//! trait Bar {
32//!     const LEN: usize;
33//!
34//!     // Error: cannot perform const operation using `Self`
35//!     fn bar(&self) -> Foo<{ Self::LEN }>;
36//! }
37//! ```
38//!
39//! **generic-array** defines a new trait [`ArrayLength`] and a struct [`GenericArray<T, N: ArrayLength>`](GenericArray),
40//! which lets the above be implemented as:
41//!
42//! ```rust
43//! use generic_array::{GenericArray, ArrayLength};
44//!
45//! struct Foo<N: ArrayLength> {
46//!     data: GenericArray<i32, N>
47//! }
48//!
49//! trait Bar {
50//!     type LEN: ArrayLength;
51//!     fn bar(&self) -> Foo<Self::LEN>;
52//! }
53//! ```
54//!
55//! The [`ArrayLength`] trait is implemented for
56//! [unsigned integer types](typenum::Unsigned) from
57//! [typenum]. For example, [`GenericArray<T, U5>`] would work almost like `[T; 5]`:
58//!
59//! ```rust
60//! # use generic_array::{ArrayLength, GenericArray};
61//! use generic_array::typenum::U5;
62//!
63//! struct Foo<T, N: ArrayLength> {
64//!     data: GenericArray<T, N>
65//! }
66//!
67//! let foo = Foo::<i32, U5> { data: GenericArray::default() };
68//! ```
69//!
70//! The `arr!` macro is provided to allow easier creation of literal arrays, as shown below:
71//!
72//! ```rust
73//! # use generic_array::arr;
74//! let array = arr![1, 2, 3];
75//! //  array: GenericArray<i32, typenum::U3>
76//! assert_eq!(array[2], 3);
77//! ```
78//! ## Feature flags
79//!
80//! ```toml
81//! [dependencies.generic-array]
82//! features = [
83//!     "serde",         # Serialize/Deserialize implementation
84//!     "zeroize",       # Zeroize implementation for setting array elements to zero
85//!     "const-default", # Compile-time const default value support via trait
86//!     "alloc",         # Enables From/TryFrom implementations between GenericArray and Vec<T>/Box<[T]>
87//!     "faster-hex",    # Enables internal use of the `faster-hex` crate for faster hex encoding via SIMD
88//!     "compat-0_14"    # Enables interoperability with `generic-array` 0.14
89//! ]
90//! ```
91
92#![deny(missing_docs)]
93#![deny(meta_variable_misuse)]
94#![no_std]
95#![cfg_attr(docsrs, feature(doc_cfg))]
96
97pub extern crate typenum;
98
99#[doc(hidden)]
100#[cfg(feature = "alloc")]
101pub extern crate alloc;
102
103mod hex;
104mod impls;
105mod iter;
106
107#[cfg(feature = "alloc")]
108mod impl_alloc;
109
110#[cfg(feature = "const-default")]
111mod impl_const_default;
112
113#[cfg(feature = "serde")]
114mod impl_serde;
115
116#[cfg(feature = "zeroize")]
117mod impl_zeroize;
118
119#[cfg(feature = "compat-0_14")]
120mod impl_compat;
121
122use core::iter::FromIterator;
123use core::marker::PhantomData;
124use core::mem::{ManuallyDrop, MaybeUninit};
125use core::ops::{Deref, DerefMut};
126use core::{mem, ptr, slice};
127use typenum::bit::{B0, B1};
128use typenum::generic_const_mappings::{Const, ToUInt};
129use typenum::uint::{UInt, UTerm, Unsigned};
130
131#[doc(hidden)]
132#[cfg_attr(test, macro_use)]
133pub mod arr;
134
135pub mod functional;
136pub mod sequence;
137
138mod internal;
139use internal::{ArrayConsumer, IntrusiveArrayBuilder, Sealed};
140
141// re-export to allow doc_auto_cfg to handle it
142#[cfg(feature = "internals")]
143pub mod internals {
144    //! Very unsafe internal functionality.
145    //!
146    //! These are used internally for building and consuming generic arrays. When used correctly,
147    //! they can ensure elements are correctly dropped if something panics while using them.
148    //!
149    //! The API of these is not guaranteed to be stable, as they are not intended for general use.
150
151    pub use crate::internal::{ArrayBuilder, ArrayConsumer, IntrusiveArrayBuilder};
152}
153
154use self::functional::*;
155use self::sequence::*;
156
157pub use self::iter::GenericArrayIter;
158
159/// `ArrayLength` is a type-level [`Unsigned`] integer used to
160/// define the number of elements in a [`GenericArray`].
161///
162/// Consider `N: ArrayLength` to be equivalent to `const N: usize`
163///
164/// ```
165/// # use generic_array::{GenericArray, ArrayLength};
166/// fn foo<N: ArrayLength>(arr: GenericArray<i32, N>) -> i32 {
167///     arr.iter().sum()
168/// }
169/// ```
170/// is equivalent to:
171/// ```
172/// fn foo<const N: usize>(arr: [i32; N]) -> i32 {
173///     arr.iter().sum()
174/// }
175/// ```
176///
177/// # Safety
178///
179/// This trait is effectively sealed due to only being allowed on [`Unsigned`] types,
180/// and therefore cannot be implemented in user code.
181///
182/// Furthermore, this is limited to lengths less than or equal to `usize::MAX`.
183/// ```compile_fail
184/// # #![recursion_limit = "256"]
185/// # use generic_array::{GenericArray, ArrayLength};
186/// # use generic_array::typenum::{self, Unsigned};
187/// type Empty = core::convert::Infallible; // Uninhabited ZST, size_of::<Empty>() == 0
188///
189/// // 2^64, greater than usize::MAX on 64-bit systems
190/// type TooBig = typenum::operator_aliases::Shleft<typenum::U1, typenum::U64>;
191///
192/// // Compile Error due to ArrayLength not implemented for TooBig
193/// let _ = GenericArray::<Empty, TooBig>::from_slice(&[]);
194/// ```
195pub unsafe trait ArrayLength: Unsigned + 'static {
196    /// Associated type representing the underlying contiguous memory
197    /// that constitutes an array with the given number of elements.
198    ///
199    /// This is an implementation detail, but is required to be public in cases where certain attributes
200    /// of the inner type of [`GenericArray`] cannot be proven, such as [`Copy`] bounds.
201    ///
202    /// [`Copy`] example:
203    /// ```
204    /// # use generic_array::{GenericArray, ArrayLength};
205    /// struct MyType<N: ArrayLength> {
206    ///     data: GenericArray<f32, N>,
207    /// }
208    ///
209    /// impl<N: ArrayLength> Clone for MyType<N> where N::ArrayType<f32>: Copy {
210    ///     fn clone(&self) -> Self { MyType { ..*self } }
211    /// }
212    ///
213    /// impl<N: ArrayLength> Copy for MyType<N> where N::ArrayType<f32>: Copy {}
214    /// ```
215    ///
216    /// Alternatively, using the entire `GenericArray<f32, N>` type as the bounds works:
217    /// ```ignore
218    /// where GenericArray<f32, N>: Copy
219    /// ```
220    type ArrayType<T>: Sealed;
221}
222
223unsafe impl ArrayLength for UTerm {
224    #[doc(hidden)]
225    type ArrayType<T> = [T; 0];
226}
227
228/// Implemented for types which can have an associated [`ArrayLength`],
229/// such as [`Const<N>`] for use with const-generics.
230///
231/// ```
232/// use generic_array::{GenericArray, IntoArrayLength, ConstArrayLength, typenum::Const};
233///
234/// fn some_array_interopt<const N: usize>(value: [u32; N]) -> GenericArray<u32, ConstArrayLength<N>>
235/// where
236///     Const<N>: IntoArrayLength,
237/// {
238///     let ga = GenericArray::from(value);
239///     // do stuff
240///     ga
241/// }
242/// ```
243///
244/// This is mostly to simplify the `where` bounds, equivalent to:
245///
246/// ```
247/// use generic_array::{GenericArray, ArrayLength, typenum::{Const, U, ToUInt}};
248///
249/// fn some_array_interopt<const N: usize>(value: [u32; N]) -> GenericArray<u32, U<N>>
250/// where
251///     Const<N>: ToUInt,
252///     U<N>: ArrayLength,
253/// {
254///     let ga = GenericArray::from(value);
255///     // do stuff
256///     ga
257/// }
258/// ```
259pub trait IntoArrayLength {
260    /// The associated `ArrayLength`
261    type ArrayLength: ArrayLength;
262}
263
264impl<const N: usize> IntoArrayLength for Const<N>
265where
266    Const<N>: ToUInt,
267    typenum::U<N>: ArrayLength,
268{
269    type ArrayLength = typenum::U<N>;
270}
271
272impl<N> IntoArrayLength for N
273where
274    N: ArrayLength,
275{
276    type ArrayLength = Self;
277}
278
279/// Associated [`ArrayLength`] for one [`Const<N>`]
280///
281/// See [`IntoArrayLength`] for more information.
282pub type ConstArrayLength<const N: usize> = <Const<N> as IntoArrayLength>::ArrayLength;
283
284/// Internal type used to generate a struct of appropriate size
285#[allow(dead_code)]
286#[repr(C)]
287#[doc(hidden)]
288pub struct GenericArrayImplEven<T, U> {
289    parents: [U; 2],
290    _marker: PhantomData<T>,
291}
292
293/// Internal type used to generate a struct of appropriate size
294#[allow(dead_code)]
295#[repr(C)]
296#[doc(hidden)]
297pub struct GenericArrayImplOdd<T, U> {
298    parents: [U; 2],
299    data: T,
300}
301
302impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
303    #[inline(always)]
304    fn clone(&self) -> GenericArrayImplEven<T, U> {
305        // Clone is never called on the GenericArrayImpl types,
306        // as we use `self.map(clone)` elsewhere. This helps avoid
307        // extra codegen for recursive clones when they are never used.
308        unsafe { core::hint::unreachable_unchecked() }
309    }
310}
311
312impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
313    #[inline(always)]
314    fn clone(&self) -> GenericArrayImplOdd<T, U> {
315        unsafe { core::hint::unreachable_unchecked() }
316    }
317}
318
319// Even if Clone is never used, they can still be byte-copyable.
320impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
321impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
322
323impl<T, U> Sealed for GenericArrayImplEven<T, U> {}
324impl<T, U> Sealed for GenericArrayImplOdd<T, U> {}
325
326// 1 << (size_of::<usize>() << 3) == usize::MAX + 1
327type MaxArrayLengthP1 = typenum::Shleft<
328    typenum::U1,
329    typenum::Shleft<typenum::U<{ mem::size_of::<usize>() }>, typenum::U3>,
330>;
331
332/// Helper trait to hide the complex bound under a simpler name
333trait IsWithinUsizeBound: typenum::IsLess<MaxArrayLengthP1, Output = typenum::consts::True> {}
334
335impl<N> IsWithinUsizeBound for N where
336    N: typenum::IsLess<MaxArrayLengthP1, Output = typenum::consts::True>
337{
338}
339
340unsafe impl<N: ArrayLength> ArrayLength for UInt<N, B0>
341where
342    Self: IsWithinUsizeBound,
343{
344    #[doc(hidden)]
345    type ArrayType<T> = GenericArrayImplEven<T, N::ArrayType<T>>;
346}
347
348unsafe impl<N: ArrayLength> ArrayLength for UInt<N, B1>
349where
350    Self: IsWithinUsizeBound,
351{
352    #[doc(hidden)]
353    type ArrayType<T> = GenericArrayImplOdd<T, N::ArrayType<T>>;
354}
355
356/// Struct representing a generic array - `GenericArray<T, N>` works like `[T; N]`
357///
358/// For how to implement [`Copy`] on structs using a generic-length `GenericArray` internally, see
359/// the docs for [`ArrayLength::ArrayType`].
360///
361/// # Usage Notes
362///
363/// ### Initialization
364///
365/// Initialization of known-length `GenericArray`s can be done via the [`arr![]`](arr!) macro,
366/// or [`from_array`](GenericArray::from_array)/[`from_slice`](GenericArray::from_slice).
367///
368/// For generic arrays of unknown/generic length, several safe methods are included to initialize
369/// them, such as the [`GenericSequence::generate`] method:
370///
371/// ```rust
372/// use generic_array::{GenericArray, sequence::GenericSequence, typenum, arr};
373///
374/// let evens: GenericArray<i32, typenum::U4> =
375///            GenericArray::generate(|i: usize| i as i32 * 2);
376///
377/// assert_eq!(evens, arr![0, 2, 4, 6]);
378/// ```
379///
380/// Furthermore, [`FromIterator`] and [`try_from_iter`](GenericArray::try_from_iter) exist to construct them
381/// from iterators, but will panic/fail if not given exactly the correct number of elements.
382///
383/// ### Utilities
384///
385/// The [`GenericSequence`], [`FunctionalSequence`], [`Lengthen`], [`Shorten`], [`Split`], and [`Concat`] traits implement
386/// some common operations on generic arrays.
387///
388/// ### Optimizations
389///
390/// Prefer to use the slice iterators like `.iter()`/`.iter_mut()` rather than by-value [`IntoIterator`]/[`GenericArrayIter`] if you can.
391/// Slices optimize better. Using the [`FunctionalSequence`] methods also optimize well.
392///
393/// # How it works
394///
395/// The `typenum` crate uses Rust's type system to define binary integers as nested types,
396/// and allows for operations which can be applied to those type-numbers, such as `Add`, `Sub`, etc.
397///
398/// e.g. `6` would be `UInt<UInt<UInt<UTerm, B1>, B1>, B0>`
399///
400/// `generic-array` uses this nested type to recursively allocate contiguous elements, statically.
401/// The [`ArrayLength`] trait is implemented on `UInt<N, B0>`, `UInt<N, B1>` and `UTerm`,
402/// which correspond to even, odd and zero numeric values, respectively.
403/// Together, these three cover all cases of `Unsigned` integers from `typenum`.
404/// For `UInt<N, B0>` and `UInt<N, B1>`, it peels away the highest binary digit and
405/// builds up a recursive structure that looks almost like a binary tree.
406/// Then, within `GenericArray`, the recursive structure is reinterpreted as a contiguous
407/// chunk of memory and allowing access to it as a slice.
408///
409/// <details>
410/// <summary><strong>Expand for internal structure demonstration</strong></summary>
411///
412/// For example, `GenericArray<T, U6>` more or less expands to (at compile time):
413///
414/// ```ignore
415/// GenericArray {
416///     // 6 = UInt<UInt<UInt<UTerm, B1>, B1>, B0>
417///     data: EvenData {
418///         // 3 = UInt<UInt<UTerm, B1>, B1>
419///         left: OddData {
420///             // 1 = UInt<UTerm, B1>
421///             left: OddData {
422///                 left: (),  // UTerm
423///                 right: (), // UTerm
424///                 data: T,   // Element 0
425///             },
426///             // 1 = UInt<UTerm, B1>
427///             right: OddData {
428///                 left: (),  // UTerm
429///                 right: (), // UTerm
430///                 data: T,   // Element 1
431///             },
432///             data: T        // Element 2
433///         },
434///         // 3 = UInt<UInt<UTerm, B1>, B1>
435///         right: OddData {
436///             // 1 = UInt<UTerm, B1>
437///             left: OddData {
438///                 left: (),  // UTerm
439///                 right: (), // UTerm
440///                 data: T,   // Element 3
441///             },
442///             // 1 = UInt<UTerm, B1>
443///             right: OddData {
444///                 left: (),  // UTerm
445///                 right: (), // UTerm
446///                 data: T,   // Element 4
447///             },
448///             data: T        // Element 5
449///         }
450///     }
451/// }
452/// ```
453///
454/// This has the added benefit of only being `log2(N)` deep, which is important for things like `Drop`
455/// to avoid stack overflows, since we can't implement `Drop` manually.
456///
457/// Then, we take the contiguous block of data and cast it to `*const T` or `*mut T` and use it as a slice:
458///
459/// ```ignore
460/// unsafe {
461///     slice::from_raw_parts(
462///         self as *const GenericArray<T, N> as *const T,
463///         <N as Unsigned>::USIZE
464///     )
465/// }
466/// ```
467///
468/// </details>
469#[repr(transparent)]
470pub struct GenericArray<T, N: ArrayLength> {
471    #[allow(dead_code)] // data is never accessed directly
472    data: N::ArrayType<T>,
473}
474
475unsafe impl<T: Send, N: ArrayLength> Send for GenericArray<T, N> {}
476unsafe impl<T: Sync, N: ArrayLength> Sync for GenericArray<T, N> {}
477
478impl<T, N: ArrayLength> Deref for GenericArray<T, N> {
479    type Target = [T];
480
481    #[inline(always)]
482    fn deref(&self) -> &[T] {
483        GenericArray::as_slice(self)
484    }
485}
486
487impl<T, N: ArrayLength> DerefMut for GenericArray<T, N> {
488    #[inline(always)]
489    fn deref_mut(&mut self) -> &mut [T] {
490        GenericArray::as_mut_slice(self)
491    }
492}
493
494impl<'a, T: 'a, N: ArrayLength> IntoIterator for &'a GenericArray<T, N> {
495    type IntoIter = slice::Iter<'a, T>;
496    type Item = &'a T;
497
498    fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {
499        self.as_slice().iter()
500    }
501}
502
503impl<'a, T: 'a, N: ArrayLength> IntoIterator for &'a mut GenericArray<T, N> {
504    type IntoIter = slice::IterMut<'a, T>;
505    type Item = &'a mut T;
506
507    fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {
508        self.as_mut_slice().iter_mut()
509    }
510}
511
512impl<T, N: ArrayLength> FromIterator<T> for GenericArray<T, N> {
513    /// Create a `GenericArray` from an iterator.
514    ///
515    /// Will panic if the number of elements is not exactly the array length.
516    ///
517    /// See [`GenericArray::try_from_iter]` for a fallible alternative.
518    #[inline]
519    fn from_iter<I>(iter: I) -> GenericArray<T, N>
520    where
521        I: IntoIterator<Item = T>,
522    {
523        match Self::try_from_iter(iter) {
524            Ok(res) => res,
525            Err(_) => from_iter_length_fail(N::USIZE),
526        }
527    }
528}
529
530#[inline(never)]
531#[cold]
532pub(crate) fn from_iter_length_fail(length: usize) -> ! {
533    panic!("GenericArray::from_iter expected {length} items");
534}
535
536unsafe impl<T, N: ArrayLength> GenericSequence<T> for GenericArray<T, N>
537where
538    Self: IntoIterator<Item = T>,
539{
540    type Length = N;
541    type Sequence = Self;
542
543    #[inline(always)]
544    fn generate<F>(mut f: F) -> GenericArray<T, N>
545    where
546        F: FnMut(usize) -> T,
547    {
548        unsafe {
549            let mut array = GenericArray::<T, N>::uninit();
550            let mut builder = IntrusiveArrayBuilder::new(&mut array);
551
552            {
553                let (builder_iter, position) = builder.iter_position();
554
555                builder_iter.enumerate().for_each(|(i, dst)| {
556                    dst.write(f(i));
557                    *position += 1;
558                });
559            }
560
561            builder.finish();
562            IntrusiveArrayBuilder::array_assume_init(array)
563        }
564    }
565
566    #[inline(always)]
567    fn inverted_zip<B, U, F>(
568        self,
569        lhs: GenericArray<B, Self::Length>,
570        mut f: F,
571    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
572    where
573        GenericArray<B, Self::Length>:
574            GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
575        Self: MappedGenericSequence<T, U>,
576        F: FnMut(B, Self::Item) -> U,
577    {
578        unsafe {
579            if mem::needs_drop::<T>() || mem::needs_drop::<B>() {
580                let mut left = ArrayConsumer::new(lhs);
581                let mut right = ArrayConsumer::new(self);
582
583                let (left_array_iter, left_position) = left.iter_position();
584                let (right_array_iter, right_position) = right.iter_position();
585
586                FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {
587                    let left_value = ptr::read(l);
588                    let right_value = ptr::read(r);
589
590                    *left_position += 1;
591                    *right_position = *left_position;
592
593                    f(left_value, right_value)
594                }))
595            } else {
596                // Despite neither needing `Drop`, they may not be `Copy`, so be paranoid
597                // and avoid anything related to drop anyway. Assume it's moved out on each read.
598                let left = ManuallyDrop::new(lhs);
599                let right = ManuallyDrop::new(self);
600
601                // Neither right nor left require `Drop` be called, so choose an iterator that's easily optimized
602                //
603                // Note that because ArrayConsumer checks for `needs_drop` itself, if `f` panics then nothing
604                // would have been done about it anyway. Only the other branch needs `ArrayConsumer`
605                FromIterator::from_iter(left.iter().zip(right.iter()).map(|(l, r)| {
606                    f(ptr::read(l), ptr::read(r)) //
607                }))
608            }
609        }
610    }
611
612    #[inline(always)]
613    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
614    where
615        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
616        Self: MappedGenericSequence<T, U>,
617        F: FnMut(Lhs::Item, Self::Item) -> U,
618    {
619        unsafe {
620            if mem::needs_drop::<T>() {
621                let mut right = ArrayConsumer::new(self);
622
623                let (right_array_iter, right_position) = right.iter_position();
624
625                FromIterator::from_iter(right_array_iter.zip(lhs).map(|(r, left_value)| {
626                    let right_value = ptr::read(r);
627
628                    *right_position += 1;
629
630                    f(left_value, right_value)
631                }))
632            } else {
633                let right = ManuallyDrop::new(self);
634
635                // Similar logic to `inverted_zip`'s no-drop branch
636                FromIterator::from_iter(right.iter().zip(lhs).map(|(r, left_value)| {
637                    f(left_value, ptr::read(r)) //
638                }))
639            }
640        }
641    }
642}
643
644impl<T, U, N: ArrayLength> MappedGenericSequence<T, U> for GenericArray<T, N>
645where
646    GenericArray<U, N>: GenericSequence<U, Length = N>,
647{
648    type Mapped = GenericArray<U, N>;
649}
650
651impl<T, N: ArrayLength> FunctionalSequence<T> for GenericArray<T, N>
652where
653    Self: GenericSequence<T, Item = T, Length = N>,
654{
655    #[inline(always)]
656    fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>
657    where
658        Self: MappedGenericSequence<T, U>,
659        F: FnMut(T) -> U,
660    {
661        unsafe {
662            let mut source = ArrayConsumer::new(self);
663
664            let (array_iter, position) = source.iter_position();
665
666            FromIterator::from_iter(array_iter.map(|src| {
667                let value = ptr::read(src);
668
669                *position += 1;
670
671                f(value)
672            }))
673        }
674    }
675
676    #[inline(always)]
677    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
678    where
679        Self: MappedGenericSequence<T, U>,
680        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
681        Rhs: GenericSequence<B, Length = Self::Length>,
682        F: FnMut(T, Rhs::Item) -> U,
683    {
684        rhs.inverted_zip(self, f)
685    }
686
687    #[inline(always)]
688    fn fold<U, F>(self, init: U, mut f: F) -> U
689    where
690        F: FnMut(U, T) -> U,
691    {
692        unsafe {
693            let mut source = ArrayConsumer::new(self);
694
695            let (array_iter, position) = source.iter_position();
696
697            array_iter.fold(init, |acc, src| {
698                let value = ptr::read(src);
699                *position += 1;
700                f(acc, value)
701            })
702        }
703    }
704}
705
706impl<T, N: ArrayLength> GenericArray<T, N> {
707    /// Returns the number of elements in the array.
708    ///
709    /// Equivalent to [`<N as Unsigned>::USIZE`](typenum::Unsigned) where `N` is the array length.
710    ///
711    /// Useful for when only a type alias is available.
712    pub const fn len() -> usize {
713        N::USIZE
714    }
715
716    /// Extracts a slice containing the entire array.
717    #[inline(always)]
718    pub const fn as_slice(&self) -> &[T] {
719        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::USIZE) }
720    }
721
722    /// Extracts a mutable slice containing the entire array.
723    ///
724    /// This method is `const` since Rust 1.83.0, but non-`const` before.
725    #[rustversion::attr(since(1.83), const)]
726    #[inline(always)]
727    pub fn as_mut_slice(&mut self) -> &mut [T] {
728        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::USIZE) }
729    }
730
731    /// Converts a slice to a generic array reference with inferred length.
732    ///
733    /// # Panics
734    ///
735    /// Panics if the slice is not equal to the length of the array.
736    ///
737    /// Consider [`TryFrom`]/[`TryInto`] for a fallible conversion,
738    /// or [`try_from_slice`](GenericArray::try_from_slice) for use in const expressions.
739    #[inline(always)]
740    pub const fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
741        if slice.len() != N::USIZE {
742            panic!("slice.len() != N in GenericArray::from_slice");
743        }
744
745        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
746    }
747
748    /// Converts a slice to a generic array reference with inferred length.
749    ///
750    /// This is a fallible alternative to [`from_slice`](GenericArray::from_slice), and can be used in const expressions,
751    /// but [`TryFrom`]/[`TryInto`] are also available to do the same thing.
752    #[inline(always)]
753    pub const fn try_from_slice(slice: &[T]) -> Result<&GenericArray<T, N>, LengthError> {
754        if slice.len() != N::USIZE {
755            return Err(LengthError);
756        }
757
758        Ok(unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) })
759    }
760
761    /// Converts a mutable slice to a mutable generic array reference with inferred length.
762    ///
763    /// # Panics
764    ///
765    /// Panics if the slice is not equal to the length of the array.
766    ///
767    /// Consider [`TryFrom`]/[`TryInto`] for a fallible conversion.
768    ///
769    /// This method is `const` since Rust 1.83.0, but non-`const` before.
770    #[rustversion::attr(since(1.83), const)]
771    #[inline(always)]
772    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
773        assert!(
774            slice.len() == N::USIZE,
775            "slice.len() != N in GenericArray::from_mut_slice"
776        );
777
778        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
779    }
780
781    /// Converts a mutable slice to a mutable generic array reference with inferred length.
782    ///
783    /// This is a fallible alternative to [`from_mut_slice`](GenericArray::from_mut_slice),
784    /// and is equivalent to the [`TryFrom`] implementation with the added benefit of being `const`.
785    ///
786    /// This method is `const` since Rust 1.83.0, but non-`const` before.
787    #[rustversion::attr(since(1.83), const)]
788    #[inline(always)]
789    pub fn try_from_mut_slice(slice: &mut [T]) -> Result<&mut GenericArray<T, N>, LengthError> {
790        match slice.len() == N::USIZE {
791            true => Ok(GenericArray::from_mut_slice(slice)),
792            false => Err(LengthError),
793        }
794    }
795
796    /// Converts a slice of `T` elements into a slice of `GenericArray<T, N>` chunks.
797    ///
798    /// Any remaining elements that do not fill the array will be returned as a second slice.
799    ///
800    /// # Panics
801    ///
802    /// Panics if `N` is `U0` _AND_ the input slice is not empty.
803    pub const fn chunks_from_slice(slice: &[T]) -> (&[GenericArray<T, N>], &[T]) {
804        if N::USIZE == 0 {
805            assert!(slice.is_empty(), "GenericArray length N must be non-zero");
806            return (&[], &[]);
807        }
808
809        // NOTE: Using `slice.split_at` adds an unnecessary assert
810        let num_chunks = slice.len() / N::USIZE; // integer division
811        let num_in_chunks = num_chunks * N::USIZE;
812        let num_remainder = slice.len() - num_in_chunks;
813
814        unsafe {
815            (
816                slice::from_raw_parts(slice.as_ptr() as *const GenericArray<T, N>, num_chunks),
817                slice::from_raw_parts(slice.as_ptr().add(num_in_chunks), num_remainder),
818            )
819        }
820    }
821
822    /// Converts a mutable slice of `T` elements into a mutable slice `GenericArray<T, N>` chunks.
823    ///
824    /// Any remaining elements that do not fill the array will be returned as a second slice.
825    ///
826    /// # Panics
827    ///
828    /// Panics if `N` is `U0` _AND_ the input slice is not empty.
829    ///
830    /// This method is `const` since Rust 1.83.0, but non-`const` before.
831    #[rustversion::attr(since(1.83), const)]
832    pub fn chunks_from_slice_mut(slice: &mut [T]) -> (&mut [GenericArray<T, N>], &mut [T]) {
833        if N::USIZE == 0 {
834            assert!(slice.is_empty(), "GenericArray length N must be non-zero");
835            return (&mut [], &mut []);
836        }
837
838        // NOTE: Using `slice.split_at_mut` adds an unnecessary assert
839        let num_chunks = slice.len() / N::USIZE; // integer division
840        let num_in_chunks = num_chunks * N::USIZE;
841        let num_remainder = slice.len() - num_in_chunks;
842
843        unsafe {
844            (
845                slice::from_raw_parts_mut(
846                    slice.as_mut_ptr() as *mut GenericArray<T, N>,
847                    num_chunks,
848                ),
849                slice::from_raw_parts_mut(slice.as_mut_ptr().add(num_in_chunks), num_remainder),
850            )
851        }
852    }
853
854    /// Convert a slice of `GenericArray<T, N>` into a slice of `T`, effectively flattening the arrays.
855    #[inline(always)]
856    pub const fn slice_from_chunks(slice: &[GenericArray<T, N>]) -> &[T] {
857        unsafe { slice::from_raw_parts(slice.as_ptr() as *const T, slice.len() * N::USIZE) }
858    }
859
860    /// Convert a slice of `GenericArray<T, N>` into a slice of `T`, effectively flattening the arrays.
861    ///
862    /// This method is `const` since Rust 1.83.0, but non-`const` before.
863    #[rustversion::attr(since(1.83), const)]
864    #[inline(always)]
865    pub fn slice_from_chunks_mut(slice: &mut [GenericArray<T, N>]) -> &mut [T] {
866        unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut T, slice.len() * N::USIZE) }
867    }
868
869    /// Convert a native array into `GenericArray` of the same length and type.
870    ///
871    /// This is the `const` equivalent of using the standard [`From`]/[`Into`] traits methods.
872    #[inline(always)]
873    pub const fn from_array<const U: usize>(value: [T; U]) -> Self
874    where
875        Const<U>: IntoArrayLength<ArrayLength = N>,
876    {
877        unsafe { crate::const_transmute(value) }
878    }
879
880    /// Convert the `GenericArray` into a native array of the same length and type.
881    ///
882    /// This is the `const` equivalent of using the standard [`From`]/[`Into`] traits methods.
883    #[inline(always)]
884    pub const fn into_array<const U: usize>(self) -> [T; U]
885    where
886        Const<U>: IntoArrayLength<ArrayLength = N>,
887    {
888        unsafe { crate::const_transmute(self) }
889    }
890
891    /// Convert a slice of native arrays into a slice of `GenericArray`s.
892    #[inline(always)]
893    pub const fn from_chunks<const U: usize>(chunks: &[[T; U]]) -> &[GenericArray<T, N>]
894    where
895        Const<U>: IntoArrayLength<ArrayLength = N>,
896    {
897        unsafe { mem::transmute(chunks) }
898    }
899
900    /// Convert a mutable slice of native arrays into a mutable slice of `GenericArray`s.
901    ///
902    /// This method is `const` since Rust 1.83.0, but non-`const` before.
903    #[rustversion::attr(since(1.83), const)]
904    #[inline(always)]
905    pub fn from_chunks_mut<const U: usize>(chunks: &mut [[T; U]]) -> &mut [GenericArray<T, N>]
906    where
907        Const<U>: IntoArrayLength<ArrayLength = N>,
908    {
909        unsafe { mem::transmute(chunks) }
910    }
911
912    /// Converts a slice `GenericArray<T, N>` into a slice of `[T; N]`
913    #[inline(always)]
914    pub const fn into_chunks<const U: usize>(chunks: &[GenericArray<T, N>]) -> &[[T; U]]
915    where
916        Const<U>: IntoArrayLength<ArrayLength = N>,
917    {
918        unsafe { mem::transmute(chunks) }
919    }
920
921    /// Converts a mutable slice `GenericArray<T, N>` into a mutable slice of `[T; N]`
922    ///
923    /// This method is `const` since Rust 1.83.0, but non-`const` before.
924    #[rustversion::attr(since(1.83), const)]
925    #[inline(always)]
926    pub fn into_chunks_mut<const U: usize>(chunks: &mut [GenericArray<T, N>]) -> &mut [[T; U]]
927    where
928        Const<U>: IntoArrayLength<ArrayLength = N>,
929    {
930        unsafe { mem::transmute(chunks) }
931    }
932}
933
934impl<T, N: ArrayLength> GenericArray<T, N> {
935    /// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
936    ///
937    /// See [`GenericArray::assume_init`] for a full example.
938    #[inline(always)]
939    #[allow(clippy::uninit_assumed_init)]
940    pub const fn uninit() -> GenericArray<MaybeUninit<T>, N> {
941        unsafe {
942            // SAFETY: An uninitialized `[MaybeUninit<_>; N]` is valid, same as regular array
943            MaybeUninit::<GenericArray<MaybeUninit<T>, N>>::uninit().assume_init()
944        }
945    }
946
947    /// Extracts the values from a generic array of `MaybeUninit` containers.
948    ///
949    /// # Safety
950    ///
951    /// It is up to the caller to guarantee that all elements of the array are in an initialized state.
952    ///
953    /// # Example
954    ///
955    /// ```
956    /// # use core::mem::MaybeUninit;
957    /// # use generic_array::{GenericArray, typenum::U3, arr};
958    /// let mut array: GenericArray<MaybeUninit<i32>, U3> = GenericArray::uninit();
959    /// array[0].write(0);
960    /// array[1].write(1);
961    /// array[2].write(2);
962    ///
963    /// // SAFETY: Now safe as we initialised all elements
964    /// let array = unsafe {
965    ///     GenericArray::assume_init(array)
966    /// };
967    ///
968    /// assert_eq!(array, arr![0, 1, 2]);
969    /// ```
970    #[inline(always)]
971    pub const unsafe fn assume_init(array: GenericArray<MaybeUninit<T>, N>) -> Self {
972        const_transmute::<_, MaybeUninit<GenericArray<T, N>>>(array).assume_init()
973    }
974}
975
976/// Error for [`TryFrom`] and [`try_from_iter`](GenericArray::try_from_iter)
977#[derive(Debug, Clone, Copy)]
978pub struct LengthError;
979
980#[rustversion::since(1.81)]
981impl core::error::Error for LengthError {}
982
983impl core::fmt::Display for LengthError {
984    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
985        f.write_str("LengthError: Slice or iterator does not match GenericArray length")
986    }
987}
988
989impl<'a, T, N: ArrayLength> TryFrom<&'a [T]> for &'a GenericArray<T, N> {
990    type Error = LengthError;
991
992    #[inline(always)]
993    fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
994        GenericArray::try_from_slice(slice)
995    }
996}
997
998impl<'a, T, N: ArrayLength> TryFrom<&'a mut [T]> for &'a mut GenericArray<T, N> {
999    type Error = LengthError;
1000
1001    #[inline(always)]
1002    fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
1003        GenericArray::try_from_mut_slice(slice)
1004    }
1005}
1006
1007impl<T, N: ArrayLength> GenericArray<T, N> {
1008    /// Fallible equivalent of [`FromIterator::from_iter`]
1009    ///
1010    /// Given iterator must yield exactly `N` elements or an error will be returned. Using [`.take(N)`](Iterator::take)
1011    /// with an iterator longer than the array may be helpful.
1012    #[inline]
1013    pub fn try_from_iter<I>(iter: I) -> Result<Self, LengthError>
1014    where
1015        I: IntoIterator<Item = T>,
1016    {
1017        let mut iter = iter.into_iter();
1018
1019        // pre-checks
1020        match iter.size_hint() {
1021            // if the lower bound is greater than N, array will overflow
1022            (n, _) if n > N::USIZE => return Err(LengthError),
1023            // if the upper bound is smaller than N, array cannot be filled
1024            (_, Some(n)) if n < N::USIZE => return Err(LengthError),
1025            _ => {}
1026        }
1027
1028        unsafe {
1029            let mut array = GenericArray::uninit();
1030            let mut builder = IntrusiveArrayBuilder::new(&mut array);
1031
1032            builder.extend(&mut iter);
1033
1034            if !builder.is_full() || iter.next().is_some() {
1035                return Err(LengthError);
1036            }
1037
1038            Ok({
1039                builder.finish();
1040                IntrusiveArrayBuilder::array_assume_init(array)
1041            })
1042        }
1043    }
1044}
1045
1046/// A const reimplementation of the [`transmute`](core::mem::transmute) function,
1047/// avoiding problems when the compiler can't prove equal sizes.
1048///
1049/// # Safety
1050/// Treat this the same as [`transmute`](core::mem::transmute), or (preferably) don't use it at all.
1051#[inline(always)]
1052#[cfg_attr(not(feature = "internals"), doc(hidden))]
1053pub const unsafe fn const_transmute<A, B>(a: A) -> B {
1054    if mem::size_of::<A>() != mem::size_of::<B>() {
1055        panic!("Size mismatch for generic_array::const_transmute");
1056    }
1057
1058    #[repr(C)]
1059    union Union<A, B> {
1060        a: ManuallyDrop<A>,
1061        b: ManuallyDrop<B>,
1062    }
1063
1064    let a = ManuallyDrop::new(a);
1065    ManuallyDrop::into_inner(Union { a }.b)
1066}
1067
1068#[cfg(test)]
1069mod test {
1070    // Compile with:
1071    // cargo rustc --lib --profile test --release --
1072    //      -C target-cpu=native -C opt-level=3 --emit asm
1073    // and view the assembly to make sure test_assembly generates
1074    // SIMD instructions instead of a naive loop.
1075
1076    #[inline(never)]
1077    pub fn black_box<T>(val: T) -> T {
1078        use core::{mem, ptr};
1079
1080        let ret = unsafe { ptr::read_volatile(&val) };
1081        mem::forget(val);
1082        ret
1083    }
1084
1085    #[test]
1086    fn test_assembly() {
1087        use crate::functional::*;
1088
1089        let a = black_box(arr![1, 3, 5, 7]);
1090        let b = black_box(arr![2, 4, 6, 8]);
1091
1092        let c = (&a).zip(b, |l, r| l + r);
1093
1094        let d = a.fold(0, |a, x| a + x);
1095
1096        assert_eq!(c, arr![3, 7, 11, 15]);
1097
1098        assert_eq!(d, 16);
1099    }
1100}