hybrid_array/
lib.rs

1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8
9//! ## Features
10//!
11//! This crate exposes the following feature flags. The default is NO features.
12//!
13//! - `bytemuck`: impls the `Pod` and `Zeroable` traits
14//! - `serde`: impls the `Deserialize` and `Serialize` traits for `Array`
15//! - `zeroize`: impls [`Zeroize`](https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html) for `Array<T: Zeroize, U>`
16//!
17//! ## Usage
18//!
19//! The two core types in this crate are as follows:
20//!
21//! - [`Array<T, U>`]: wrapper for `[T; N]` where `U` is an [`ArraySize`] provided by [`typenum`]
22//!   whose associated [`ArraySize::ArrayType<T>`] determines the inner array size.
23//! - [`ArrayN<T, N>`]: type alias for [`Array`] which is const generic around `const N: usize`.
24//!   This provides a linkage between const generics and [`typenum`].
25//!
26//! The [`Array`] type has an inner `pub [T; N]` field, which means writing a literal can be
27//! expressed as follows:
28//!
29//! ```
30//! use hybrid_array::{Array, sizes::U4};
31//!
32//! let arr: Array<u8, U4> = Array([1, 2, 3, 4]);
33//! ```
34//!
35//! ### About [`typenum`]
36//!
37//! The [`typenum`] crate provides a type-level implementation of numbers and arithmetic operations.
38//!
39//! While [`typenum`] can be used to express arbitrary integers using the type system, the
40//! `hybrid-array` crate is limited to the array sizes in the [`sizes`] module, which have
41//! names like [`U0`][`sizes::U0`], [`U1`][`sizes::U1`], [`U2`][`sizes::U2`], [`U3`][`sizes::U3`],
42//! etc. All supported sizes will have an impl of [`ArraySize`], which is the trait providing
43//! linkage between [`typenum`]-based types and core arrays / const generics.
44//!
45//! [`ArraySize`] bounds on the [`typenum::Unsigned`] trait, which can be used to obtain integer
46//! sizes of arrays via associated constants. For example, to obtain the size of an `ArraySize` as
47//! a `usize`, use the associated [`typenum::Unsigned::USIZE`] constant.
48//!
49//! ### [`AsArrayRef`] and [`AsArrayMut`] traits
50//!
51//! These traits simplify obtaining references to [`Array`] and are impl'd for both [`Array`]
52//! and `[T; N]`. They're analogous to traits like [`AsRef`] and [`AsMut`].
53//!
54//! They make it possible to write code which uses `[T; N]` or `&[T; N]` in the external facing
55//! API which can obtain references to `&Array` and call other functions which accept such
56//! references, without the caller having to use `Array` in their code and while still supporting
57//! generic sizes.
58//!
59//! For more information and a code example, see [`AsArrayRef`].
60//!
61//! ## Relationship with `generic-array`
62//!
63//! `hybrid-array` is directly inspired by the [`generic-array`] crate.
64//!
65//! However, where `generic-array` predates const generics and uses a core which is built
66//! on `unsafe` code, `hybrid-array`'s core implementation is built on safe code and const
67//! generic implementations. This allows the inner `[T; N]` field of an `Array` to be `pub` as
68//! noted above, and in general for the implementation to be significantly simpler, easier-to-audit,
69//! and with significantly less use of `unsafe`.
70//!
71//! The only places `hybrid-array` uses unsafe are where it is absolutely necessary, primarily
72//! for reference conversions between `Array<T, U>` and `[T; N]`, and also to provide features
73//! which are not yet stable in `core`/`std`, such as [`Array::try_from_fn`].
74//!
75//! [`generic-array`]: https://docs.rs/generic-array
76//!
77//! ## Migrating from `generic-array`
78//!
79//! *NOTE: this guide assumes a migration from `generic-array` v0.14*
80//!
81//! `hybrid-array` has been designed to largely be a drop-in replacement for
82//! `generic-array`, albeit with a public inner array type and significantly less
83//! `unsafe` code.
84//!
85//! The bulk of the migration work can be accomplished by making the following find/replace-style
86//! substitutions in your `.rs` files:
87//!
88//! - Replace `generic_array` with `hybrid_array`
89//! - Replace `GenericArray<T, U>` with `Array<T, U>`
90//! - Replace `ArrayLength<T>` with `ArraySize`
91//! - Replace usages of the `Concat` and `Split` traits with [`Array::concat`] and [`Array::split`]
92//! - Replace `<U as ArrayLength<T>>::ArrayType` with `<U as ArraySize>::ArrayType<T>`
93//! - Replace usages of the `arr![N; A, B, C]` macro with `Array([A, B, C])`
94//!
95//! If you have any questions, please
96//! [start a discussion](https://github.com/RustCrypto/hybrid-array/discussions).
97
98#[cfg(feature = "alloc")]
99extern crate alloc;
100
101pub mod sizes;
102
103mod from_fn;
104mod iter;
105mod traits;
106
107#[cfg(feature = "serde")]
108mod serde;
109
110pub use crate::{iter::TryFromIteratorError, traits::*};
111pub use typenum;
112
113use core::{
114    array::TryFromSliceError,
115    borrow::{Borrow, BorrowMut},
116    cmp::Ordering,
117    fmt::{self, Debug},
118    hash::{Hash, Hasher},
119    mem::{self, ManuallyDrop, MaybeUninit},
120    ops::{Add, Deref, DerefMut, Index, IndexMut, Sub},
121    ptr,
122    slice::{self, Iter, IterMut},
123};
124use typenum::{Diff, Sum};
125
126#[cfg(feature = "arbitrary")]
127use arbitrary::Arbitrary;
128
129#[cfg(feature = "bytemuck")]
130use bytemuck::{Pod, Zeroable};
131
132#[cfg(feature = "subtle")]
133use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
134
135#[cfg(feature = "zeroize")]
136use zeroize::{Zeroize, ZeroizeOnDrop};
137
138#[cfg(feature = "zerocopy")]
139use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
140
141/// Type alias for [`Array`] which is const generic around a size `N`, ala `[T; N]`.
142pub type ArrayN<T, const N: usize> = Array<T, <[T; N] as AssocArraySize>::Size>;
143
144/// [`Array`] is a newtype for an inner `[T; N]` array where `N` is determined by a generic
145/// [`ArraySize`] parameter, which is a marker trait for a numeric value determined by ZSTs that
146/// impl the [`typenum::Unsigned`] trait.
147///
148/// The inner `[T; N]` field is `pub` which means it's possible to write [`Array`] literals like:
149///
150/// [`Array`] is defined as `repr(transparent)`, meaning it can be used anywhere an appropriately
151/// sized `[T; N]` type is used in unsafe code / FFI.
152///
153/// ```
154/// use hybrid_array::{Array, sizes::U3};
155///
156/// let arr: Array<u8, U3> = Array([1, 2, 3]);
157/// ```
158#[cfg_attr(
159    feature = "zerocopy",
160    derive(IntoBytes, FromBytes, Immutable, Unaligned, KnownLayout)
161)]
162#[repr(transparent)]
163pub struct Array<T, U: ArraySize>(pub U::ArrayType<T>);
164
165type SplitResult<T, U, N> = (Array<T, N>, Array<T, Diff<U, N>>);
166type SplitRefResult<'a, T, U, N> = (&'a Array<T, N>, &'a Array<T, Diff<U, N>>);
167type SplitRefMutResult<'a, T, U, N> = (&'a mut Array<T, N>, &'a mut Array<T, Diff<U, N>>);
168
169impl<T, U> Array<T, U>
170where
171    U: ArraySize,
172{
173    /// Returns a slice containing the entire array. Equivalent to `&s[..]`.
174    #[inline]
175    pub const fn as_slice(&self) -> &[T] {
176        // SAFETY: `[T]` is layout-identical to `Array<T, U>`, which is a `repr(transparent)`
177        // newtype for `[T; N]`.
178        unsafe { slice::from_raw_parts(self.as_ptr(), U::USIZE) }
179    }
180
181    /// Returns a mutable slice containing the entire array. Equivalent to `&mut s[..]`.
182    #[inline]
183    pub const fn as_mut_slice(&mut self) -> &mut [T] {
184        // SAFETY: `[T]` is layout-identical to `Array<T, U>`, which is a `repr(transparent)`
185        // newtype for `[T; N]`.
186        unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), U::USIZE) }
187    }
188
189    /// Returns a pointer to the start of the array.
190    pub const fn as_ptr(&self) -> *const T {
191        ptr::from_ref::<Self>(self).cast::<T>()
192    }
193
194    /// Returns a mutable pointer to the start of the array.
195    pub const fn as_mut_ptr(&mut self) -> *mut T {
196        ptr::from_mut::<Self>(self).cast::<T>()
197    }
198
199    /// Returns an iterator over the array.
200    #[inline]
201    pub fn iter(&self) -> Iter<'_, T> {
202        self.as_slice().iter()
203    }
204
205    /// Returns an iterator that allows modifying each value.
206    #[inline]
207    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
208        self.as_mut().iter_mut()
209    }
210
211    /// Returns an array of the same size as `self`, with function `f` applied to each element in
212    /// order.
213    pub fn map<F, O>(self, f: F) -> Array<O, U>
214    where
215        F: FnMut(T) -> O,
216    {
217        self.into_iter().map(f).collect()
218    }
219
220    /// Concatenates `self` with `other`.
221    #[inline]
222    pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
223    where
224        N: ArraySize,
225        U: Add<N>,
226        Sum<U, N>: ArraySize,
227    {
228        let mut c = Array::uninit();
229        let (left, right) = c.split_at_mut(self.len());
230        for (val, dst) in self.into_iter().zip(left) {
231            dst.write(val);
232        }
233        for (val, dst) in other.into_iter().zip(right) {
234            dst.write(val);
235        }
236        // SAFETY: We wrote to every element of `c`.
237        unsafe { c.assume_init() }
238    }
239
240    /// Splits `self` at index `N` in two arrays.
241    ///
242    /// New arrays hold the original memory from `self`.
243    #[inline]
244    pub fn split<N>(self) -> SplitResult<T, U, N>
245    where
246        U: Sub<N>,
247        N: ArraySize,
248        Diff<U, N>: ArraySize,
249    {
250        unsafe {
251            let array = ManuallyDrop::new(self);
252            let head = ptr::read(array.as_ptr().cast());
253            let tail = ptr::read(array.as_ptr().add(N::USIZE).cast());
254            (head, tail)
255        }
256    }
257
258    /// Splits `&self` at index `N` in two array references.
259    #[inline]
260    pub fn split_ref<N>(&self) -> SplitRefResult<'_, T, U, N>
261    where
262        U: Sub<N>,
263        N: ArraySize,
264        Diff<U, N>: ArraySize,
265    {
266        unsafe {
267            let array_ptr = self.as_ptr();
268            let head = &*array_ptr.cast();
269            let tail = &*array_ptr.add(N::USIZE).cast();
270            (head, tail)
271        }
272    }
273
274    /// Splits `&mut self` at index `N` in two mutable array references.
275    #[inline]
276    pub fn split_ref_mut<N>(&mut self) -> SplitRefMutResult<'_, T, U, N>
277    where
278        U: Sub<N>,
279        N: ArraySize,
280        Diff<U, N>: ArraySize,
281    {
282        unsafe {
283            let array_ptr = self.as_mut_ptr();
284            let head = &mut *array_ptr.cast();
285            let tail = &mut *array_ptr.add(N::USIZE).cast();
286            (head, tail)
287        }
288    }
289
290    /// Splits the shared slice into a slice of `U`-element arrays, starting at the beginning
291    /// of the slice, and a remainder slice with length strictly less than `U`.
292    ///
293    /// # Panics
294    /// Panics if `U` is 0.
295    #[allow(clippy::arithmetic_side_effects)]
296    #[inline]
297    pub const fn slice_as_chunks(buf: &[T]) -> (&[Self], &[T]) {
298        assert!(U::USIZE != 0, "chunk size must be non-zero");
299        // Arithmetic safety: we have checked that `N::USIZE` is not zero, thus
300        // division always returns correct result. `tail_pos` can not be bigger than `buf.len()`,
301        // thus overflow on multiplication and underflow on substraction are impossible.
302        let chunks_len = buf.len() / U::USIZE;
303        let tail_pos = U::USIZE * chunks_len;
304        let tail_len = buf.len() - tail_pos;
305        unsafe {
306            let ptr = buf.as_ptr();
307            let chunks = slice::from_raw_parts(ptr.cast(), chunks_len);
308            let tail = slice::from_raw_parts(ptr.add(tail_pos), tail_len);
309            (chunks, tail)
310        }
311    }
312
313    /// Splits the exclusive slice into a slice of `U`-element arrays, starting at the beginning
314    /// of the slice, and a remainder slice with length strictly less than `U`.
315    ///
316    /// # Panics
317    /// Panics if `U` is 0.
318    #[allow(clippy::arithmetic_side_effects)]
319    #[inline]
320    pub const fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Self], &mut [T]) {
321        assert!(U::USIZE != 0, "chunk size must be non-zero");
322        // Arithmetic safety: we have checked that `N::USIZE` is not zero, thus
323        // division always returns correct result. `tail_pos` can not be bigger than `buf.len()`,
324        // thus overflow on multiplication and underflow on substraction are impossible.
325        let chunks_len = buf.len() / U::USIZE;
326        let tail_pos = U::USIZE * chunks_len;
327        let tail_len = buf.len() - tail_pos;
328        unsafe {
329            let ptr = buf.as_mut_ptr();
330            let chunks = slice::from_raw_parts_mut(ptr.cast(), chunks_len);
331            let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len);
332            (chunks, tail)
333        }
334    }
335
336    /// Obtain a flattened slice from a slice of array chunks.
337    ///
338    /// # Panics
339    /// - if the length calculation for the flattened slice overflows
340    #[inline]
341    pub const fn slice_as_flattened(slice: &[Self]) -> &[T] {
342        let len = slice
343            .len()
344            .checked_mul(U::USIZE)
345            .expect("slice len overflow");
346
347        // SAFETY: `[T]` is layout-identical to `Array<T, U>`, which is a `repr(transparent)`
348        // newtype for `[T; N]`.
349        unsafe { slice::from_raw_parts(slice.as_ptr().cast(), len) }
350    }
351
352    /// Obtain a mutable flattened slice from a mutable slice of array chunks.
353    ///
354    /// # Panics
355    /// - if the length calculation for the flattened slice overflows
356    #[inline]
357    pub const fn slice_as_flattened_mut(slice: &mut [Self]) -> &mut [T] {
358        let len = slice
359            .len()
360            .checked_mul(U::USIZE)
361            .expect("slice len overflow");
362
363        // SAFETY: `[T]` is layout-identical to `Array<T, U>`, which is a `repr(transparent)`
364        // newtype for `[T; N]`.
365        unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), len) }
366    }
367}
368
369impl<T, U, V> Array<Array<T, U>, V>
370where
371    U: ArraySize,
372    V: ArraySize,
373{
374    /// Takes a `&Array<Array<T, N>, >>`, and flattens it to a `&[T]`.
375    ///
376    /// # Panics
377    ///
378    /// This panics if the length of the resulting slice would overflow a `usize`.
379    ///
380    /// This is only possible when flattening a slice of arrays of zero-sized
381    /// types, and thus tends to be irrelevant in practice. If
382    /// `size_of::<T>() > 0`, this will never panic.
383    ///
384    /// # Examples
385    ///
386    /// ```
387    /// use hybrid_array::{Array, typenum::{U0, U2, U3, U5, U10}};
388    ///
389    /// let a: Array<Array<usize, U3>, U2> = Array([Array([1, 2, 3]), Array([4, 5, 6])]);
390    /// assert_eq!(a.as_flattened(), &[1, 2, 3, 4, 5, 6]);
391    ///
392    /// let b: Array<Array<usize, U2>, U3> = Array([Array([1, 2]), Array([3, 4]), Array([5, 6])]);
393    /// assert_eq!(a.as_flattened(), b.as_flattened());
394    ///
395    /// let c: Array<[usize; 2], U3> = Array([[1, 2], [3, 4], [5, 6]]);
396    /// assert_eq!(a.as_flattened(), c.as_flattened());
397    ///
398    /// let slice_of_empty_arrays: &Array<Array<i32, U5>, U0> = &Array::from_fn(|_| Array([1, 2, 3, 4, 5]));
399    /// assert!(slice_of_empty_arrays.as_flattened().is_empty());
400    ///
401    /// let empty_slice_of_arrays: &Array<Array<u32, U10>, U0>  = &Array([]);
402    /// assert!(empty_slice_of_arrays.as_flattened().is_empty());
403    /// ```
404    pub const fn as_flattened(&self) -> &[T] {
405        Array::slice_as_flattened(self.as_slice())
406    }
407
408    /// Takes a `&mut Array<Array<T, N>,M>`, and flattens it to a `&mut [T]`.
409    ///
410    /// # Panics
411    ///
412    /// This panics if the length of the resulting slice would overflow a `usize`.
413    ///
414    /// This is only possible when flattening a slice of arrays of zero-sized
415    /// types, and thus tends to be irrelevant in practice. If
416    /// `size_of::<T>() > 0`, this will never panic.
417    ///
418    /// # Examples
419    ///
420    /// ```
421    /// use hybrid_array::{Array, typenum::U3};
422    ///
423    /// fn add_5_to_all(slice: &mut [i32]) {
424    ///     for i in slice {
425    ///         *i += 5;
426    ///     }
427    /// }
428    ///
429    /// let mut array: Array<Array<i32, U3>, U3> = Array([Array([1_i32, 2, 3]), Array([4, 5, 6]), Array([7, 8, 9])]);
430    /// add_5_to_all(array.as_flattened_mut());
431    /// assert_eq!(array, Array([Array([6, 7, 8]), Array([9, 10, 11]), Array([12, 13, 14])]));
432    /// ```
433    pub const fn as_flattened_mut(&mut self) -> &mut [T] {
434        Array::slice_as_flattened_mut(self.as_mut_slice())
435    }
436}
437
438// Impls which depend on the inner array type being `[T; N]`.
439impl<T, U, const N: usize> Array<T, U>
440where
441    U: ArraySize<ArrayType<T> = [T; N]>,
442{
443    /// Transform slice to slice of core array type.
444    #[inline]
445    pub const fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
446        // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; N]`
447        unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
448    }
449
450    /// Transform mutable slice to mutable slice of core array type.
451    #[inline]
452    pub const fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
453        // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; N]`
454        unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
455    }
456
457    /// Transform slice to slice of core array type.
458    #[inline]
459    pub const fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
460        // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; N]`
461        unsafe { slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
462    }
463
464    /// Transform mutable slice to mutable slice of core array type.
465    #[inline]
466    pub const fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
467        // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; N]`
468        unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
469    }
470}
471
472impl<T, U> Array<MaybeUninit<T>, U>
473where
474    U: ArraySize,
475{
476    /// Create an uninitialized array of [`MaybeUninit`]s for the given type.
477    #[must_use]
478    pub const fn uninit() -> Array<MaybeUninit<T>, U> {
479        // SAFETY: `Array` is a `repr(transparent)` newtype for `[MaybeUninit<T>, N]`, i.e. an
480        // array of uninitialized memory mediated via the `MaybeUninit` interface, where the inner
481        // type is constrained by `ArraySize` impls which can only be added by this crate.
482        //
483        // Calling `uninit().assume_init()` triggers the `clippy::uninit_assumed_init` lint, but
484        // as just mentioned the inner type we're "assuming init" for is `[MaybeUninit<T>, N]`,
485        // i.e. an array of uninitialized memory, which is always valid because definitionally no
486        // initialization is required of uninitialized memory.
487        #[allow(clippy::uninit_assumed_init)]
488        Self(unsafe { MaybeUninit::uninit().assume_init() })
489    }
490
491    /// Extract the values from an array of `MaybeUninit` containers.
492    ///
493    /// # Safety
494    ///
495    /// It is up to the caller to guarantee that all elements of the array are in an initialized
496    /// state.
497    #[inline]
498    pub unsafe fn assume_init(self) -> Array<T, U> {
499        unsafe {
500            // `Array` is a `repr(transparent)` newtype for a generic inner type which is constrained to
501            // be `[T; N]` by the `ArraySize` impls in this crate.
502            //
503            // Since we're working with a type-erased inner type and ultimately trying to convert
504            // `[MaybeUninit<T>; N]` to `[T; N]`, we can't use simpler approaches like a pointer cast
505            // or `transmute`, since the compiler can't prove to itself that the size will be the same.
506            //
507            // We've taken unique ownership of `self`, which is a `MaybeUninit` array, and as such we
508            // don't need to worry about `Drop` impls because `MaybeUninit` does not impl `Drop`.
509            // Since we have unique ownership of `self`, it's okay to make a copy because we're throwing
510            // the original away (and this should all get optimized to a noop by the compiler, anyway).
511            mem::transmute_copy(&self)
512        }
513    }
514}
515
516impl<T, U> AsRef<Array<T, U>> for Array<T, U>
517where
518    U: ArraySize,
519{
520    #[inline]
521    fn as_ref(&self) -> &Self {
522        self
523    }
524}
525
526impl<T, U> AsRef<[T]> for Array<T, U>
527where
528    U: ArraySize,
529{
530    #[inline]
531    fn as_ref(&self) -> &[T] {
532        self.0.as_ref()
533    }
534}
535
536impl<T, U, const N: usize> AsRef<[T; N]> for Array<T, U>
537where
538    U: ArraySize<ArrayType<T> = [T; N]>,
539{
540    #[inline]
541    fn as_ref(&self) -> &[T; N] {
542        &self.0
543    }
544}
545
546impl<T, U> AsMut<[T]> for Array<T, U>
547where
548    U: ArraySize,
549{
550    #[inline]
551    fn as_mut(&mut self) -> &mut [T] {
552        self.0.as_mut()
553    }
554}
555
556impl<T, U, const N: usize> AsMut<[T; N]> for Array<T, U>
557where
558    U: ArraySize<ArrayType<T> = [T; N]>,
559{
560    #[inline]
561    fn as_mut(&mut self) -> &mut [T; N] {
562        &mut self.0
563    }
564}
565
566impl<T, U> Borrow<[T]> for Array<T, U>
567where
568    U: ArraySize,
569{
570    #[inline]
571    fn borrow(&self) -> &[T] {
572        self.0.as_ref()
573    }
574}
575
576impl<T, U, const N: usize> Borrow<[T; N]> for Array<T, U>
577where
578    U: ArraySize<ArrayType<T> = [T; N]>,
579{
580    #[inline]
581    fn borrow(&self) -> &[T; N] {
582        &self.0
583    }
584}
585
586impl<T, U> BorrowMut<[T]> for Array<T, U>
587where
588    U: ArraySize,
589{
590    #[inline]
591    fn borrow_mut(&mut self) -> &mut [T] {
592        self.0.as_mut()
593    }
594}
595
596impl<T, U, const N: usize> BorrowMut<[T; N]> for Array<T, U>
597where
598    U: ArraySize<ArrayType<T> = [T; N]>,
599{
600    #[inline]
601    fn borrow_mut(&mut self) -> &mut [T; N] {
602        &mut self.0
603    }
604}
605
606impl<T, U> Clone for Array<T, U>
607where
608    T: Clone,
609    U: ArraySize,
610{
611    #[inline]
612    fn clone(&self) -> Self {
613        Self::from_fn(|n| self.0.as_ref()[n].clone())
614    }
615}
616
617impl<T, U> Copy for Array<T, U>
618where
619    T: Copy,
620    U: ArraySize,
621    U::ArrayType<T>: Copy,
622{
623}
624
625impl<T, U> Debug for Array<T, U>
626where
627    T: Debug,
628    U: ArraySize,
629{
630    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
631        f.debug_tuple("Array").field(&self.0.as_ref()).finish()
632    }
633}
634
635impl<T, U> Default for Array<T, U>
636where
637    T: Default,
638    U: ArraySize,
639{
640    #[inline]
641    fn default() -> Self {
642        Self::from_fn(|_| Default::default())
643    }
644}
645
646impl<T, U> Deref for Array<T, U>
647where
648    U: ArraySize,
649{
650    type Target = [T];
651
652    #[inline]
653    fn deref(&self) -> &[T] {
654        self.0.as_ref()
655    }
656}
657
658impl<T, U> DerefMut for Array<T, U>
659where
660    U: ArraySize,
661{
662    #[inline]
663    fn deref_mut(&mut self) -> &mut [T] {
664        self.0.as_mut()
665    }
666}
667
668impl<T, U> Eq for Array<T, U>
669where
670    T: Eq,
671    U: ArraySize,
672{
673}
674
675impl<T, U, const N: usize> From<[T; N]> for Array<T, U>
676where
677    U: ArraySize<ArrayType<T> = [T; N]>,
678{
679    #[inline]
680    fn from(arr: [T; N]) -> Array<T, U> {
681        Array(arr)
682    }
683}
684
685impl<T, U, const N: usize> From<Array<T, U>> for [T; N]
686where
687    U: ArraySize<ArrayType<T> = [T; N]>,
688{
689    #[inline]
690    fn from(arr: Array<T, U>) -> [T; N] {
691        arr.0
692    }
693}
694
695impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array<T, U>
696where
697    U: ArraySize<ArrayType<T> = [T; N]>,
698{
699    #[inline]
700    fn from(array_ref: &'a [T; N]) -> &'a Array<T, U> {
701        // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]`
702        unsafe { &*array_ref.as_ptr().cast() }
703    }
704}
705
706impl<'a, T, U, const N: usize> From<&'a Array<T, U>> for &'a [T; N]
707where
708    U: ArraySize<ArrayType<T> = [T; N]>,
709{
710    #[inline]
711    fn from(array_ref: &'a Array<T, U>) -> &'a [T; N] {
712        array_ref.as_ref()
713    }
714}
715
716impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array<T, U>
717where
718    U: ArraySize<ArrayType<T> = [T; N]>,
719{
720    #[inline]
721    fn from(array_ref: &'a mut [T; N]) -> &'a mut Array<T, U> {
722        // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]`
723        unsafe { &mut *array_ref.as_mut_ptr().cast() }
724    }
725}
726
727impl<'a, T, U, const N: usize> From<&'a mut Array<T, U>> for &'a mut [T; N]
728where
729    U: ArraySize<ArrayType<T> = [T; N]>,
730{
731    #[inline]
732    fn from(array_ref: &'a mut Array<T, U>) -> &'a mut [T; N] {
733        array_ref.as_mut()
734    }
735}
736
737#[cfg(feature = "alloc")]
738impl<T, U> From<Array<T, U>> for alloc::boxed::Box<[T]>
739where
740    U: ArraySize,
741{
742    #[inline]
743    fn from(array: Array<T, U>) -> alloc::boxed::Box<[T]> {
744        array.into_iter().collect()
745    }
746}
747
748#[cfg(feature = "alloc")]
749impl<T, U> From<&Array<T, U>> for alloc::boxed::Box<[T]>
750where
751    T: Clone,
752    U: ArraySize,
753{
754    #[inline]
755    fn from(array: &Array<T, U>) -> alloc::boxed::Box<[T]> {
756        array.as_slice().into()
757    }
758}
759
760#[cfg(feature = "alloc")]
761impl<T, U> From<Array<T, U>> for alloc::vec::Vec<T>
762where
763    U: ArraySize,
764{
765    #[inline]
766    fn from(array: Array<T, U>) -> alloc::vec::Vec<T> {
767        array.into_iter().collect()
768    }
769}
770
771#[cfg(feature = "alloc")]
772impl<T, U> From<&Array<T, U>> for alloc::vec::Vec<T>
773where
774    T: Clone,
775    U: ArraySize,
776{
777    #[inline]
778    fn from(array: &Array<T, U>) -> alloc::vec::Vec<T> {
779        array.as_slice().into()
780    }
781}
782
783impl<T, U> Hash for Array<T, U>
784where
785    T: Hash,
786    U: ArraySize,
787{
788    #[inline]
789    fn hash<H: Hasher>(&self, state: &mut H) {
790        self.0.as_ref().hash(state);
791    }
792}
793
794impl<T, I, U> Index<I> for Array<T, U>
795where
796    [T]: Index<I>,
797    U: ArraySize,
798{
799    type Output = <[T] as Index<I>>::Output;
800
801    #[inline]
802    fn index(&self, index: I) -> &Self::Output {
803        Index::index(self.as_slice(), index)
804    }
805}
806
807impl<T, I, U> IndexMut<I> for Array<T, U>
808where
809    [T]: IndexMut<I>,
810    U: ArraySize,
811{
812    #[inline]
813    fn index_mut(&mut self, index: I) -> &mut Self::Output {
814        IndexMut::index_mut(self.as_mut_slice(), index)
815    }
816}
817
818impl<T, U> PartialEq for Array<T, U>
819where
820    T: PartialEq,
821    U: ArraySize,
822{
823    #[inline]
824    fn eq(&self, other: &Self) -> bool {
825        self.0.as_ref().eq(other.0.as_ref())
826    }
827}
828
829impl<T, U, const N: usize> PartialEq<[T; N]> for Array<T, U>
830where
831    T: PartialEq,
832    U: ArraySize<ArrayType<T> = [T; N]>,
833{
834    #[inline]
835    fn eq(&self, other: &[T; N]) -> bool {
836        self.0.eq(other)
837    }
838}
839
840impl<T, U, const N: usize> PartialEq<Array<T, U>> for [T; N]
841where
842    T: PartialEq,
843    U: ArraySize<ArrayType<T> = [T; N]>,
844{
845    #[inline]
846    fn eq(&self, other: &Array<T, U>) -> bool {
847        self.eq(&other.0)
848    }
849}
850
851impl<T, U> PartialOrd for Array<T, U>
852where
853    T: PartialOrd,
854    U: ArraySize,
855{
856    #[inline]
857    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
858        self.0.as_ref().partial_cmp(other.0.as_ref())
859    }
860}
861
862impl<T, U> Ord for Array<T, U>
863where
864    T: Ord,
865    U: ArraySize,
866{
867    #[inline]
868    fn cmp(&self, other: &Self) -> Ordering {
869        self.0.as_ref().cmp(other.0.as_ref())
870    }
871}
872
873/// SAFETY: `Array` is a `repr(transparent)` newtype for `[T; N]`, so as long as `T: Send` it should
874/// also be `Send`.
875unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
876
877/// SAFETY: `Array` is a `repr(transparent)` newtype for `[T; N]`, so as long as `T: Sync` it should
878/// also be `Sync`.
879unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
880
881impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
882where
883    Self: Clone,
884    U: ArraySize,
885{
886    type Error = TryFromSliceError;
887
888    #[inline]
889    fn try_from(slice: &'a [T]) -> Result<Array<T, U>, TryFromSliceError> {
890        <&'a Self>::try_from(slice).cloned()
891    }
892}
893
894#[cfg(feature = "alloc")]
895impl<T, U> TryFrom<alloc::boxed::Box<[T]>> for Array<T, U>
896where
897    Self: Clone,
898    U: ArraySize,
899{
900    type Error = TryFromSliceError;
901
902    #[inline]
903    fn try_from(b: alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
904        Self::try_from(&*b)
905    }
906}
907
908#[cfg(feature = "alloc")]
909impl<'a, T, U> TryFrom<&'a alloc::boxed::Box<[T]>> for Array<T, U>
910where
911    Self: Clone,
912    U: ArraySize,
913{
914    type Error = TryFromSliceError;
915
916    #[inline]
917    fn try_from(b: &'a alloc::boxed::Box<[T]>) -> Result<Self, TryFromSliceError> {
918        Self::try_from(&**b)
919    }
920}
921
922#[cfg(feature = "alloc")]
923impl<T, U> TryFrom<alloc::vec::Vec<T>> for Array<T, U>
924where
925    Self: Clone,
926    U: ArraySize,
927{
928    type Error = TryFromSliceError;
929
930    #[inline]
931    fn try_from(v: alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
932        Self::try_from(v.as_slice())
933    }
934}
935
936#[cfg(feature = "alloc")]
937impl<'a, T, U> TryFrom<&'a alloc::vec::Vec<T>> for Array<T, U>
938where
939    Self: Clone,
940    U: ArraySize,
941{
942    type Error = TryFromSliceError;
943
944    #[inline]
945    fn try_from(v: &'a alloc::vec::Vec<T>) -> Result<Self, TryFromSliceError> {
946        Self::try_from(v.as_slice())
947    }
948}
949
950impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
951where
952    U: ArraySize,
953{
954    type Error = TryFromSliceError;
955
956    #[inline]
957    fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
958        check_slice_length::<T, U>(slice)?;
959
960        // SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
961        // array with length checked above.
962        Ok(unsafe { &*slice.as_ptr().cast() })
963    }
964}
965
966impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
967where
968    U: ArraySize,
969{
970    type Error = TryFromSliceError;
971
972    #[inline]
973    fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
974        check_slice_length::<T, U>(slice)?;
975
976        // SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
977        // array with length checked above.
978        Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
979    }
980}
981
982// Deprecated legacy methods to ease migrations from `generic-array`
983impl<T, U> Array<T, U>
984where
985    U: ArraySize,
986{
987    /// Convert the given slice into a reference to a hybrid array.
988    ///
989    /// # Panics
990    ///
991    /// Panics if the slice's length doesn't match the array type.
992    #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
993    #[inline]
994    pub fn from_slice(slice: &[T]) -> &Self {
995        slice.try_into().expect("slice length mismatch")
996    }
997
998    /// Convert the given mutable slice to a mutable reference to a hybrid array.
999    ///
1000    /// # Panics
1001    ///
1002    /// Panics if the slice's length doesn't match the array type.
1003    #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1004    #[inline]
1005    pub fn from_mut_slice(slice: &mut [T]) -> &mut Self {
1006        slice.try_into().expect("slice length mismatch")
1007    }
1008
1009    /// Clone the contents of the slice as a new hybrid array.
1010    ///
1011    /// # Panics
1012    ///
1013    /// Panics if the slice's length doesn't match the array type.
1014    #[deprecated(since = "0.2.0", note = "use `TryFrom` instead")]
1015    #[inline]
1016    pub fn clone_from_slice(slice: &[T]) -> Self
1017    where
1018        Self: Clone,
1019    {
1020        slice.try_into().expect("slice length mismatch")
1021    }
1022}
1023
1024#[cfg(feature = "arbitrary")]
1025impl<'a, T, U> Arbitrary<'a> for Array<T, U>
1026where
1027    T: Arbitrary<'a>,
1028    U: ArraySize,
1029{
1030    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1031        Self::try_from_fn(|_n| Arbitrary::arbitrary(u))
1032    }
1033}
1034
1035#[cfg(feature = "bytemuck")]
1036unsafe impl<T, U> Pod for Array<T, U>
1037where
1038    T: Pod,
1039    U: ArraySize,
1040    U::ArrayType<T>: Copy,
1041{
1042}
1043
1044#[cfg(feature = "bytemuck")]
1045unsafe impl<T, U> Zeroable for Array<T, U>
1046where
1047    T: Zeroable,
1048    U: ArraySize,
1049{
1050}
1051
1052#[cfg(feature = "subtle")]
1053impl<T, U> ConditionallySelectable for Array<T, U>
1054where
1055    Self: Copy,
1056    T: ConditionallySelectable,
1057    U: ArraySize,
1058{
1059    #[inline]
1060    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
1061        let mut output = *a;
1062        output.conditional_assign(b, choice);
1063        output
1064    }
1065
1066    fn conditional_assign(&mut self, other: &Self, choice: Choice) {
1067        for (a_i, b_i) in self.iter_mut().zip(other) {
1068            a_i.conditional_assign(b_i, choice);
1069        }
1070    }
1071}
1072
1073#[cfg(feature = "subtle")]
1074impl<T, U> ConstantTimeEq for Array<T, U>
1075where
1076    T: ConstantTimeEq,
1077    U: ArraySize,
1078{
1079    #[inline]
1080    fn ct_eq(&self, other: &Self) -> Choice {
1081        self.iter()
1082            .zip(other.iter())
1083            .fold(Choice::from(1), |acc, (a, b)| acc & a.ct_eq(b))
1084    }
1085}
1086
1087#[cfg(feature = "zeroize")]
1088impl<T, U> Zeroize for Array<T, U>
1089where
1090    T: Zeroize,
1091    U: ArraySize,
1092{
1093    #[inline]
1094    fn zeroize(&mut self) {
1095        self.0.as_mut().iter_mut().zeroize();
1096    }
1097}
1098
1099#[cfg(feature = "zeroize")]
1100impl<T, U> ZeroizeOnDrop for Array<T, U>
1101where
1102    T: ZeroizeOnDrop,
1103    U: ArraySize,
1104{
1105}
1106
1107/// Generate a [`TryFromSliceError`] if the slice doesn't match the given length.
1108#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
1109fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
1110    debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);
1111
1112    if slice.len() != U::USIZE {
1113        // Hack: `TryFromSliceError` lacks a public constructor
1114        <&[T; 1]>::try_from([].as_slice())?;
1115
1116        #[cfg(debug_assertions)]
1117        unreachable!();
1118    }
1119
1120    Ok(())
1121}