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//!     "compat-0_14",      # Enables interoperability with `generic-array` 0.14
137//!     "hybrid-array-0_4"  # Enables interoperability with `hybrid-array` 0.4
138//! ]
139//! ```
140
141#![deny(missing_docs)]
142#![deny(meta_variable_misuse)]
143#![no_std]
144#![cfg_attr(docsrs, feature(doc_cfg))]
145
146pub extern crate typenum;
147
148#[doc(hidden)]
149#[cfg(feature = "alloc")]
150pub extern crate alloc;
151
152mod compat;
153mod hex;
154mod impls;
155mod iter;
156
157#[cfg(feature = "alloc")]
158mod impl_alloc;
159
160#[cfg(feature = "const-default")]
161mod impl_const_default;
162
163#[cfg(feature = "serde")]
164mod impl_serde;
165
166#[cfg(feature = "zeroize")]
167mod impl_zeroize;
168
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
364impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
365    #[inline(always)]
366    fn clone(&self) -> GenericArrayImplEven<T, U> {
367        // Clone is never called on the GenericArrayImpl types,
368        // as we use `self.map(clone)` elsewhere. This helps avoid
369        // extra codegen for recursive clones when they are never used.
370        unsafe { core::hint::unreachable_unchecked() }
371    }
372}
373
374impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
375    #[inline(always)]
376    fn clone(&self) -> GenericArrayImplOdd<T, U> {
377        unsafe { core::hint::unreachable_unchecked() }
378    }
379}
380
381// Even if Clone is never used, they can still be byte-copyable.
382impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
383impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
384
385impl<T, U> Sealed for GenericArrayImplEven<T, U> {}
386impl<T, U> Sealed for GenericArrayImplOdd<T, U> {}
387
388// 1 << (size_of::<usize>() << 3) == usize::MAX + 1
389type MaxArrayLengthP1 = typenum::Shleft<
390    typenum::U1,
391    typenum::Shleft<typenum::U<{ mem::size_of::<usize>() }>, typenum::U3>,
392>;
393
394/// Helper trait to hide the complex bound under a simpler name
395trait IsWithinUsizeBound: typenum::IsLess<MaxArrayLengthP1, Output = typenum::consts::True> {}
396
397impl<N> IsWithinUsizeBound for N where
398    N: typenum::IsLess<MaxArrayLengthP1, Output = typenum::consts::True>
399{
400}
401
402unsafe impl<N: ArrayLength> ArrayLength for UInt<N, B0>
403where
404    Self: IsWithinUsizeBound,
405{
406    #[doc(hidden)]
407    type ArrayType<T> = GenericArrayImplEven<T, N::ArrayType<T>>;
408}
409
410unsafe impl<N: ArrayLength> ArrayLength for UInt<N, B1>
411where
412    Self: IsWithinUsizeBound,
413{
414    #[doc(hidden)]
415    type ArrayType<T> = GenericArrayImplOdd<T, N::ArrayType<T>>;
416}
417
418/// Struct representing a generic array - `GenericArray<T, N>` works like `[T; N]`
419///
420/// For how to implement [`Copy`] on structs using a generic-length `GenericArray` internally, see
421/// the docs for [`ArrayLength::ArrayType`].
422///
423/// # Usage Notes
424///
425/// ### Initialization
426///
427/// Initialization of known-length `GenericArray`s can be done via the [`arr![]`](arr!) macro,
428/// or [`from_array`](GenericArray::from_array)/[`from_slice`](GenericArray::from_slice).
429///
430/// For generic arrays of unknown/generic length, several safe methods are included to initialize
431/// them, such as the [`GenericSequence::generate`] method:
432///
433/// ```rust
434/// use generic_array::{GenericArray, sequence::GenericSequence, typenum, arr};
435///
436/// let evens: GenericArray<i32, typenum::U4> =
437///            GenericArray::generate(|i: usize| i as i32 * 2);
438///
439/// assert_eq!(evens, arr![0, 2, 4, 6]);
440/// ```
441///
442/// Furthermore, [`FromIterator`] and [`try_from_iter`](GenericArray::try_from_iter) exist to construct them
443/// from iterators, but will panic/fail if not given exactly the correct number of elements.
444///
445/// ### Utilities
446///
447/// The [`GenericSequence`], [`FunctionalSequence`], [`Lengthen`], [`Shorten`], [`Split`], and [`Concat`] traits implement
448/// some common operations on generic arrays.
449///
450/// ### Optimizations
451///
452/// Prefer to use the slice iterators like `.iter()`/`.iter_mut()` rather than by-value [`IntoIterator`]/[`GenericArrayIter`] if you can.
453/// Slices optimize better. Using the [`FunctionalSequence`] methods also optimize well.
454///
455/// # How it works
456///
457/// The `typenum` crate uses Rust's type system to define binary integers as nested types,
458/// and allows for operations which can be applied to those type-numbers, such as `Add`, `Sub`, etc.
459///
460/// e.g. `6` would be `UInt<UInt<UInt<UTerm, B1>, B1>, B0>`
461///
462/// `generic-array` uses this nested type to recursively allocate contiguous elements, statically.
463/// The [`ArrayLength`] trait is implemented on `UInt<N, B0>`, `UInt<N, B1>` and `UTerm`,
464/// which correspond to even, odd and zero numeric values, respectively.
465/// Together, these three cover all cases of `Unsigned` integers from `typenum`.
466/// For `UInt<N, B0>` and `UInt<N, B1>`, it peels away the highest binary digit and
467/// builds up a recursive structure that looks almost like a binary tree.
468/// Then, within `GenericArray`, the recursive structure is reinterpreted as a contiguous
469/// chunk of memory and allowing access to it as a slice.
470///
471/// <details>
472/// <summary><strong>Expand for internal structure demonstration</strong></summary>
473///
474/// For example, `GenericArray<T, U6>` more or less expands to (at compile time):
475///
476/// ```ignore
477/// GenericArray {
478///     // 6 = UInt<UInt<UInt<UTerm, B1>, B1>, B0>
479///     data: EvenData {
480///         // 3 = UInt<UInt<UTerm, B1>, B1>
481///         left: OddData {
482///             // 1 = UInt<UTerm, B1>
483///             left: OddData {
484///                 left: (),  // UTerm
485///                 right: (), // UTerm
486///                 data: T,   // Element 0
487///             },
488///             // 1 = UInt<UTerm, B1>
489///             right: OddData {
490///                 left: (),  // UTerm
491///                 right: (), // UTerm
492///                 data: T,   // Element 1
493///             },
494///             data: T        // Element 2
495///         },
496///         // 3 = UInt<UInt<UTerm, B1>, B1>
497///         right: OddData {
498///             // 1 = UInt<UTerm, B1>
499///             left: OddData {
500///                 left: (),  // UTerm
501///                 right: (), // UTerm
502///                 data: T,   // Element 3
503///             },
504///             // 1 = UInt<UTerm, B1>
505///             right: OddData {
506///                 left: (),  // UTerm
507///                 right: (), // UTerm
508///                 data: T,   // Element 4
509///             },
510///             data: T        // Element 5
511///         }
512///     }
513/// }
514/// ```
515///
516/// This has the added benefit of only being `log2(N)` deep, which is important for things like `Drop`
517/// to avoid stack overflows, since we can't implement `Drop` manually.
518///
519/// Then, we take the contiguous block of data and cast it to `*const T` or `*mut T` and use it as a slice:
520///
521/// ```ignore
522/// unsafe {
523///     slice::from_raw_parts(
524///         self as *const GenericArray<T, N> as *const T,
525///         <N as Unsigned>::USIZE
526///     )
527/// }
528/// ```
529///
530/// </details>
531#[repr(transparent)]
532pub struct GenericArray<T, N: ArrayLength> {
533    #[allow(dead_code)] // data is never accessed directly
534    data: N::ArrayType<T>,
535}
536
537unsafe impl<T: Send, N: ArrayLength> Send for GenericArray<T, N> {}
538unsafe impl<T: Sync, N: ArrayLength> Sync for GenericArray<T, N> {}
539
540impl<T, N: ArrayLength> Deref for GenericArray<T, N> {
541    type Target = [T];
542
543    #[inline(always)]
544    fn deref(&self) -> &[T] {
545        GenericArray::as_slice(self)
546    }
547}
548
549impl<T, N: ArrayLength> DerefMut for GenericArray<T, N> {
550    #[inline(always)]
551    fn deref_mut(&mut self) -> &mut [T] {
552        GenericArray::as_mut_slice(self)
553    }
554}
555
556impl<'a, T: 'a, N: ArrayLength> IntoIterator for &'a GenericArray<T, N> {
557    type IntoIter = slice::Iter<'a, T>;
558    type Item = &'a T;
559
560    fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {
561        self.as_slice().iter()
562    }
563}
564
565impl<'a, T: 'a, N: ArrayLength> IntoIterator for &'a mut GenericArray<T, N> {
566    type IntoIter = slice::IterMut<'a, T>;
567    type Item = &'a mut T;
568
569    fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {
570        self.as_mut_slice().iter_mut()
571    }
572}
573
574impl<T, N: ArrayLength> FromIterator<T> for GenericArray<T, N> {
575    /// Create a `GenericArray` from an iterator.
576    ///
577    /// Will panic if the number of elements is not exactly the array length.
578    ///
579    /// See [`GenericArray::try_from_iter]` for a fallible alternative.
580    #[inline]
581    fn from_iter<I>(iter: I) -> GenericArray<T, N>
582    where
583        I: IntoIterator<Item = T>,
584    {
585        match Self::try_from_iter(iter) {
586            Ok(res) => res,
587            Err(_) => from_iter_length_fail(N::USIZE),
588        }
589    }
590}
591
592#[inline(never)]
593#[cold]
594pub(crate) fn from_iter_length_fail(length: usize) -> ! {
595    panic!("GenericArray::from_iter expected {length} items");
596}
597
598unsafe impl<T, N: ArrayLength> GenericSequence<T> for GenericArray<T, N>
599where
600    Self: IntoIterator<Item = T>,
601{
602    type Length = N;
603    type Sequence = Self;
604
605    #[inline(always)]
606    fn generate<F>(mut f: F) -> GenericArray<T, N>
607    where
608        F: FnMut(usize) -> T,
609    {
610        unsafe {
611            let mut array = MaybeUninit::<GenericArray<T, N>>::uninit();
612            let mut builder = IntrusiveArrayBuilder::new_alt(&mut array);
613
614            {
615                let (builder_iter, position) = builder.iter_position();
616
617                builder_iter.enumerate().for_each(|(i, dst)| {
618                    dst.write(f(i));
619                    *position += 1;
620                });
621            }
622
623            builder.finish_and_assume_init()
624        }
625    }
626
627    #[inline(always)]
628    fn inverted_zip<B, U, F>(
629        self,
630        lhs: GenericArray<B, Self::Length>,
631        mut f: F,
632    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
633    where
634        GenericArray<B, Self::Length>:
635            GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
636        Self: MappedGenericSequence<T, U>,
637        F: FnMut(B, Self::Item) -> U,
638    {
639        unsafe {
640            if mem::needs_drop::<T>() || mem::needs_drop::<B>() {
641                let mut left = ManuallyDrop::new(lhs);
642                let mut right = ManuallyDrop::new(self);
643
644                let mut left = IntrusiveArrayConsumer::new(&mut left);
645                let mut right = IntrusiveArrayConsumer::new(&mut right);
646
647                let (left_array_iter, left_position) = left.iter_position();
648                let (right_array_iter, right_position) = right.iter_position();
649
650                FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {
651                    let left_value = ptr::read(l);
652                    let right_value = ptr::read(r);
653
654                    *left_position += 1;
655                    *right_position = *left_position;
656
657                    f(left_value, right_value)
658                }))
659            } else {
660                // Despite neither needing `Drop`, they may not be `Copy`, so be paranoid
661                // and avoid anything related to drop anyway. Assume it's moved out on each read.
662                let left = ManuallyDrop::new(lhs);
663                let right = ManuallyDrop::new(self);
664
665                // Neither right nor left require `Drop` be called, so choose an iterator that's easily optimized
666                //
667                // Note that because ArrayConsumer checks for `needs_drop` itself, if `f` panics then nothing
668                // would have been done about it anyway. Only the other branch needs `ArrayConsumer`
669                FromIterator::from_iter(left.iter().zip(right.iter()).map(|(l, r)| {
670                    f(ptr::read(l), ptr::read(r)) //
671                }))
672            }
673        }
674    }
675
676    #[inline(always)]
677    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
678    where
679        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
680        Self: MappedGenericSequence<T, U>,
681        F: FnMut(Lhs::Item, Self::Item) -> U,
682    {
683        unsafe {
684            if mem::needs_drop::<T>() {
685                let mut right = ManuallyDrop::new(self);
686                let mut right = IntrusiveArrayConsumer::new(&mut right);
687
688                let (right_array_iter, right_position) = right.iter_position();
689
690                FromIterator::from_iter(right_array_iter.zip(lhs).map(|(r, left_value)| {
691                    let right_value = ptr::read(r);
692
693                    *right_position += 1;
694
695                    f(left_value, right_value)
696                }))
697            } else {
698                let right = ManuallyDrop::new(self);
699
700                // Similar logic to `inverted_zip`'s no-drop branch
701                FromIterator::from_iter(right.iter().zip(lhs).map(|(r, left_value)| {
702                    f(left_value, ptr::read(r)) //
703                }))
704            }
705        }
706    }
707}
708
709impl<T, U, N: ArrayLength> MappedGenericSequence<T, U> for GenericArray<T, N>
710where
711    GenericArray<U, N>: GenericSequence<U, Length = N>,
712{
713    type Mapped = GenericArray<U, N>;
714}
715
716impl<T, N: ArrayLength> FunctionalSequence<T> for GenericArray<T, N>
717where
718    Self: GenericSequence<T, Item = T, Length = N>,
719{
720    #[inline(always)]
721    fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>
722    where
723        Self: MappedGenericSequence<T, U>,
724        F: FnMut(T) -> U,
725    {
726        unsafe {
727            let mut array = ManuallyDrop::new(self);
728            let mut source = IntrusiveArrayConsumer::new(&mut array);
729
730            let (array_iter, position) = source.iter_position();
731
732            FromIterator::from_iter(array_iter.map(|src| {
733                let value = ptr::read(src);
734
735                *position += 1;
736
737                f(value)
738            }))
739        }
740    }
741
742    #[inline(always)]
743    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
744    where
745        Self: MappedGenericSequence<T, U>,
746        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
747        Rhs: GenericSequence<B, Length = Self::Length>,
748        F: FnMut(T, Rhs::Item) -> U,
749    {
750        rhs.inverted_zip(self, f)
751    }
752
753    #[inline(always)]
754    fn fold<U, F>(self, init: U, mut f: F) -> U
755    where
756        F: FnMut(U, T) -> U,
757    {
758        unsafe {
759            let mut array = ManuallyDrop::new(self);
760            let mut source = IntrusiveArrayConsumer::new(&mut array);
761
762            let (array_iter, position) = source.iter_position();
763
764            array_iter.fold(init, |acc, src| {
765                let value = ptr::read(src);
766                *position += 1;
767                f(acc, value)
768            })
769        }
770    }
771}
772
773impl<T, N: ArrayLength> GenericArray<T, N> {
774    /// Returns the number of elements in the array.
775    ///
776    /// Equivalent to [`<N as Unsigned>::USIZE`](typenum::Unsigned) where `N` is the array length.
777    ///
778    /// Useful for when only a type alias is available.
779    pub const fn len() -> usize {
780        N::USIZE
781    }
782
783    /// Extracts a slice containing the entire array.
784    #[inline(always)]
785    pub const fn as_slice(&self) -> &[T] {
786        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::USIZE) }
787    }
788
789    /// Extracts a mutable slice containing the entire array.
790    ///
791    /// This method is `const` since Rust 1.83.0, but non-`const` before.
792    #[rustversion::attr(since(1.83), const)]
793    #[inline(always)]
794    pub fn as_mut_slice(&mut self) -> &mut [T] {
795        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::USIZE) }
796    }
797
798    /// Converts a slice to a generic array reference with inferred length.
799    ///
800    /// # Panics
801    ///
802    /// Panics if the slice is not equal to the length of the array.
803    ///
804    /// Consider [`TryFrom`]/[`TryInto`] for a fallible conversion,
805    /// or [`try_from_slice`](GenericArray::try_from_slice) for use in const expressions.
806    #[inline(always)]
807    pub const fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
808        if slice.len() != N::USIZE {
809            panic!("slice.len() != N in GenericArray::from_slice");
810        }
811
812        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
813    }
814
815    /// Converts a slice to a generic array reference with inferred length.
816    ///
817    /// This is a fallible alternative to [`from_slice`](GenericArray::from_slice), and can be used in const expressions,
818    /// but [`TryFrom`]/[`TryInto`] are also available to do the same thing.
819    #[inline(always)]
820    pub const fn try_from_slice(slice: &[T]) -> Result<&GenericArray<T, N>, LengthError> {
821        if slice.len() != N::USIZE {
822            return Err(LengthError);
823        }
824
825        Ok(unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) })
826    }
827
828    /// Converts a mutable slice to a mutable generic array reference with inferred length.
829    ///
830    /// # Panics
831    ///
832    /// Panics if the slice is not equal to the length of the array.
833    ///
834    /// Consider [`TryFrom`]/[`TryInto`] for a fallible conversion.
835    ///
836    /// This method is `const` since Rust 1.83.0, but non-`const` before.
837    #[rustversion::attr(since(1.83), const)]
838    #[inline(always)]
839    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
840        assert!(
841            slice.len() == N::USIZE,
842            "slice.len() != N in GenericArray::from_mut_slice"
843        );
844
845        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
846    }
847
848    /// Converts a mutable slice to a mutable generic array reference with inferred length.
849    ///
850    /// This is a fallible alternative to [`from_mut_slice`](GenericArray::from_mut_slice),
851    /// and is equivalent to the [`TryFrom`] implementation with the added benefit of being `const`.
852    ///
853    /// This method is `const` since Rust 1.83.0, but non-`const` before.
854    #[rustversion::attr(since(1.83), const)]
855    #[inline(always)]
856    pub fn try_from_mut_slice(slice: &mut [T]) -> Result<&mut GenericArray<T, N>, LengthError> {
857        match slice.len() == N::USIZE {
858            true => Ok(GenericArray::from_mut_slice(slice)),
859            false => Err(LengthError),
860        }
861    }
862
863    /// Converts a slice of `T` elements into a slice of `GenericArray<T, N>` chunks.
864    ///
865    /// Any remaining elements that do not fill the array will be returned as a second slice.
866    ///
867    /// # Panics
868    ///
869    /// Panics if `N` is `U0` _AND_ the input slice is not empty.
870    pub const fn chunks_from_slice(slice: &[T]) -> (&[GenericArray<T, N>], &[T]) {
871        if N::USIZE == 0 {
872            assert!(slice.is_empty(), "GenericArray length N must be non-zero");
873            return (&[], &[]);
874        }
875
876        // NOTE: Using `slice.split_at` adds an unnecessary assert
877        let num_chunks = slice.len() / N::USIZE; // integer division
878        let num_in_chunks = num_chunks * N::USIZE;
879        let num_remainder = slice.len() - num_in_chunks;
880
881        unsafe {
882            (
883                slice::from_raw_parts(slice.as_ptr() as *const GenericArray<T, N>, num_chunks),
884                slice::from_raw_parts(slice.as_ptr().add(num_in_chunks), num_remainder),
885            )
886        }
887    }
888
889    /// Converts a mutable slice of `T` elements into a mutable slice `GenericArray<T, N>` chunks.
890    ///
891    /// Any remaining elements that do not fill the array will be returned as a second slice.
892    ///
893    /// # Panics
894    ///
895    /// Panics if `N` is `U0` _AND_ the input slice is not empty.
896    ///
897    /// This method is `const` since Rust 1.83.0, but non-`const` before.
898    #[rustversion::attr(since(1.83), const)]
899    pub fn chunks_from_slice_mut(slice: &mut [T]) -> (&mut [GenericArray<T, N>], &mut [T]) {
900        if N::USIZE == 0 {
901            assert!(slice.is_empty(), "GenericArray length N must be non-zero");
902            return (&mut [], &mut []);
903        }
904
905        // NOTE: Using `slice.split_at_mut` adds an unnecessary assert
906        let num_chunks = slice.len() / N::USIZE; // integer division
907        let num_in_chunks = num_chunks * N::USIZE;
908        let num_remainder = slice.len() - num_in_chunks;
909
910        unsafe {
911            (
912                slice::from_raw_parts_mut(
913                    slice.as_mut_ptr() as *mut GenericArray<T, N>,
914                    num_chunks,
915                ),
916                slice::from_raw_parts_mut(slice.as_mut_ptr().add(num_in_chunks), num_remainder),
917            )
918        }
919    }
920
921    /// Convert a slice of `GenericArray<T, N>` into a slice of `T`, effectively flattening the arrays.
922    #[inline(always)]
923    pub const fn slice_from_chunks(slice: &[GenericArray<T, N>]) -> &[T] {
924        unsafe { slice::from_raw_parts(slice.as_ptr() as *const T, slice.len() * N::USIZE) }
925    }
926
927    /// Convert a slice of `GenericArray<T, N>` into a slice of `T`, effectively flattening the arrays.
928    ///
929    /// This method is `const` since Rust 1.83.0, but non-`const` before.
930    #[rustversion::attr(since(1.83), const)]
931    #[inline(always)]
932    pub fn slice_from_chunks_mut(slice: &mut [GenericArray<T, N>]) -> &mut [T] {
933        unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut T, slice.len() * N::USIZE) }
934    }
935
936    /// Convert a native array into `GenericArray` of the same length and type.
937    ///
938    /// This is the `const` equivalent of using the standard [`From`]/[`Into`] traits methods.
939    #[inline(always)]
940    pub const fn from_array<const U: usize>(value: [T; U]) -> Self
941    where
942        Const<U>: IntoArrayLength<ArrayLength = N>,
943    {
944        unsafe { crate::const_transmute(value) }
945    }
946
947    /// Convert the `GenericArray` into a native array of the same length and type.
948    ///
949    /// This is the `const` equivalent of using the standard [`From`]/[`Into`] traits methods.
950    #[inline(always)]
951    pub const fn into_array<const U: usize>(self) -> [T; U]
952    where
953        Const<U>: IntoArrayLength<ArrayLength = N>,
954    {
955        unsafe { crate::const_transmute(self) }
956    }
957
958    /// Convert a slice of native arrays into a slice of `GenericArray`s.
959    #[inline(always)]
960    pub const fn from_chunks<const U: usize>(chunks: &[[T; U]]) -> &[GenericArray<T, N>]
961    where
962        Const<U>: IntoArrayLength<ArrayLength = N>,
963    {
964        unsafe { mem::transmute(chunks) }
965    }
966
967    /// Convert a mutable slice of native arrays into a mutable slice of `GenericArray`s.
968    ///
969    /// This method is `const` since Rust 1.83.0, but non-`const` before.
970    #[rustversion::attr(since(1.83), const)]
971    #[inline(always)]
972    pub fn from_chunks_mut<const U: usize>(chunks: &mut [[T; U]]) -> &mut [GenericArray<T, N>]
973    where
974        Const<U>: IntoArrayLength<ArrayLength = N>,
975    {
976        unsafe { mem::transmute(chunks) }
977    }
978
979    /// Converts a slice `GenericArray<T, N>` into a slice of `[T; N]`
980    #[inline(always)]
981    pub const fn into_chunks<const U: usize>(chunks: &[GenericArray<T, N>]) -> &[[T; U]]
982    where
983        Const<U>: IntoArrayLength<ArrayLength = N>,
984    {
985        unsafe { mem::transmute(chunks) }
986    }
987
988    /// Converts a mutable slice `GenericArray<T, N>` into a mutable slice of `[T; N]`
989    ///
990    /// This method is `const` since Rust 1.83.0, but non-`const` before.
991    #[rustversion::attr(since(1.83), const)]
992    #[inline(always)]
993    pub fn into_chunks_mut<const U: usize>(chunks: &mut [GenericArray<T, N>]) -> &mut [[T; U]]
994    where
995        Const<U>: IntoArrayLength<ArrayLength = N>,
996    {
997        unsafe { mem::transmute(chunks) }
998    }
999}
1000
1001impl<T, N: ArrayLength> GenericArray<T, N> {
1002    /// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
1003    ///
1004    /// See [`GenericArray::assume_init`] for a full example.
1005    #[inline(always)]
1006    #[allow(clippy::uninit_assumed_init)]
1007    pub const fn uninit() -> GenericArray<MaybeUninit<T>, N> {
1008        unsafe {
1009            // SAFETY: An uninitialized `[MaybeUninit<_>; N]` is valid, same as regular array
1010            MaybeUninit::<GenericArray<MaybeUninit<T>, N>>::uninit().assume_init()
1011        }
1012    }
1013
1014    /// Extracts the values from a generic array of `MaybeUninit` containers.
1015    ///
1016    /// # Safety
1017    ///
1018    /// It is up to the caller to guarantee that all elements of the array are in an initialized state.
1019    ///
1020    /// # Example
1021    ///
1022    /// ```
1023    /// # use core::mem::MaybeUninit;
1024    /// # use generic_array::{GenericArray, typenum::U3, arr};
1025    /// let mut array: GenericArray<MaybeUninit<i32>, U3> = GenericArray::uninit();
1026    /// array[0].write(0);
1027    /// array[1].write(1);
1028    /// array[2].write(2);
1029    ///
1030    /// // SAFETY: Now safe as we initialised all elements
1031    /// let array = unsafe {
1032    ///     GenericArray::assume_init(array)
1033    /// };
1034    ///
1035    /// assert_eq!(array, arr![0, 1, 2]);
1036    /// ```
1037    #[inline(always)]
1038    pub const unsafe fn assume_init(array: GenericArray<MaybeUninit<T>, N>) -> Self {
1039        const_transmute::<GenericArray<MaybeUninit<T>, N>, GenericArray<T, N>>(array)
1040    }
1041}
1042
1043/// Error for [`TryFrom`] and [`try_from_iter`](GenericArray::try_from_iter)
1044#[derive(Debug, Clone, Copy)]
1045pub struct LengthError;
1046
1047#[rustversion::since(1.81)]
1048impl core::error::Error for LengthError {}
1049
1050impl core::fmt::Display for LengthError {
1051    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1052        f.write_str("LengthError: Slice or iterator does not match GenericArray length")
1053    }
1054}
1055
1056impl<'a, T, N: ArrayLength> TryFrom<&'a [T]> for &'a GenericArray<T, N> {
1057    type Error = LengthError;
1058
1059    #[inline(always)]
1060    fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
1061        GenericArray::try_from_slice(slice)
1062    }
1063}
1064
1065impl<'a, T, N: ArrayLength> TryFrom<&'a mut [T]> for &'a mut GenericArray<T, N> {
1066    type Error = LengthError;
1067
1068    #[inline(always)]
1069    fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
1070        GenericArray::try_from_mut_slice(slice)
1071    }
1072}
1073
1074impl<T, N: ArrayLength> GenericArray<T, N> {
1075    /// Fallible equivalent of [`FromIterator::from_iter`]
1076    ///
1077    /// Given iterator must yield exactly `N` elements or an error will be returned. Using [`.take(N)`](Iterator::take)
1078    /// with an iterator longer than the array may be helpful.
1079    #[inline]
1080    pub fn try_from_iter<I>(iter: I) -> Result<Self, LengthError>
1081    where
1082        I: IntoIterator<Item = T>,
1083    {
1084        let mut iter = iter.into_iter();
1085
1086        // pre-checks
1087        match iter.size_hint() {
1088            // if the lower bound is greater than N, array will overflow
1089            (n, _) if n > N::USIZE => return Err(LengthError),
1090            // if the upper bound is smaller than N, array cannot be filled
1091            (_, Some(n)) if n < N::USIZE => return Err(LengthError),
1092            _ => {}
1093        }
1094
1095        unsafe {
1096            let mut array = MaybeUninit::<GenericArray<T, N>>::uninit();
1097            let mut builder = IntrusiveArrayBuilder::new_alt(&mut array);
1098
1099            builder.extend(&mut iter);
1100
1101            if !builder.is_full() || iter.next().is_some() {
1102                return Err(LengthError);
1103            }
1104
1105            Ok(builder.finish_and_assume_init())
1106        }
1107    }
1108}
1109
1110/// A const reimplementation of the [`transmute`](core::mem::transmute) function,
1111/// avoiding problems when the compiler can't prove equal sizes for some reason.
1112///
1113/// This will still check that the sizes of `A` and `B` are equal at compile time:
1114/// ```compile_fail
1115/// # use generic_array::const_transmute;
1116///
1117/// let _ = unsafe { const_transmute::<u32, u64>(0u32) }; // panics at compile time
1118/// ```
1119///
1120/// # Safety
1121/// Treat this the same as [`transmute`](core::mem::transmute), or (preferably) don't use it at all.
1122#[inline(always)]
1123#[cfg_attr(not(feature = "internals"), doc(hidden))]
1124pub const unsafe fn const_transmute<A, B>(a: A) -> B {
1125    struct SizeAsserter<A, B>(PhantomData<(A, B)>);
1126
1127    impl<A, B> SizeAsserter<A, B> {
1128        const ASSERT_SIZE_EQUALITY: () = {
1129            if mem::size_of::<A>() != mem::size_of::<B>() {
1130                panic!("Size mismatch for generic_array::const_transmute");
1131            }
1132        };
1133    }
1134
1135    let () = SizeAsserter::<A, B>::ASSERT_SIZE_EQUALITY;
1136
1137    #[rustversion::since(1.74)]
1138    #[inline(always)]
1139    const unsafe fn do_transmute<A, B>(a: A) -> B {
1140        mem::transmute_copy(&ManuallyDrop::new(a))
1141    }
1142
1143    #[rustversion::before(1.74)]
1144    #[inline(always)]
1145    const unsafe fn do_transmute<A, B>(a: A) -> B {
1146        #[repr(C)]
1147        union Union<A, B> {
1148            a: ManuallyDrop<A>,
1149            b: ManuallyDrop<B>,
1150        }
1151
1152        let a = ManuallyDrop::new(a);
1153        ManuallyDrop::into_inner(Union { a }.b)
1154    }
1155
1156    do_transmute(a)
1157}
1158
1159#[cfg(test)]
1160mod test {
1161    // Compile with:
1162    // cargo rustc --lib --profile test --release --
1163    //      -C target-cpu=native -C opt-level=3 --emit asm
1164    // and view the assembly to make sure test_assembly generates
1165    // SIMD instructions instead of a naive loop.
1166
1167    #[inline(never)]
1168    pub fn black_box<T>(val: T) -> T {
1169        use core::{mem, ptr};
1170
1171        let ret = unsafe { ptr::read_volatile(&val) };
1172        mem::forget(val);
1173        ret
1174    }
1175
1176    #[test]
1177    fn test_assembly() {
1178        use crate::functional::*;
1179
1180        let a = black_box(arr![1, 3, 5, 7]);
1181        let b = black_box(arr![2, 4, 6, 8]);
1182
1183        let c = (&a).zip(b, |l, r| l + r);
1184
1185        let d = a.fold(0, |a, x| a + x);
1186
1187        assert_eq!(c, arr![3, 7, 11, 15]);
1188
1189        assert_eq!(d, 16);
1190    }
1191}