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