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