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