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