Skip to main content

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