generic_array/
lib.rs

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