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