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