generic_array/
lib.rs

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