Skip to main content

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