generic_array/
lib.rs

1//! This crate implements a structure that can be used as a generic array type.
2//! Core Rust array types `[T; N]` can't be used generically with
3//! respect to `N`, so for example this:
4//!
5//! ```rust{compile_fail}
6//! struct Foo<T, N> {
7//!     data: [T; N]
8//! }
9//! ```
10//!
11//! won't work.
12//!
13//! **generic-array** exports a `GenericArray<T,N>` type, which lets
14//! the above be implemented as:
15//!
16//! ```rust
17//! use generic_array::{ArrayLength, GenericArray};
18//!
19//! struct Foo<T, N: ArrayLength<T>> {
20//!     data: GenericArray<T,N>
21//! }
22//! ```
23//!
24//! The `ArrayLength<T>` trait is implemented by default for
25//! [unsigned integer types](../typenum/uint/index.html) from
26//! [typenum](../typenum/index.html):
27//!
28//! ```rust
29//! # use generic_array::{ArrayLength, GenericArray};
30//! use generic_array::typenum::U5;
31//!
32//! struct Foo<N: ArrayLength<i32>> {
33//!     data: GenericArray<i32, N>
34//! }
35//!
36//! # fn main() {
37//! let foo = Foo::<U5>{data: GenericArray::default()};
38//! # }
39//! ```
40//!
41//! For example, `GenericArray<T, U5>` would work almost like `[T; 5]`:
42//!
43//! ```rust
44//! # use generic_array::{ArrayLength, GenericArray};
45//! use generic_array::typenum::U5;
46//!
47//! struct Foo<T, N: ArrayLength<T>> {
48//!     data: GenericArray<T, N>
49//! }
50//!
51//! # fn main() {
52//! let foo = Foo::<i32, U5>{data: GenericArray::default()};
53//! # }
54//! ```
55//!
56//! For ease of use, an `arr!` macro is provided - example below:
57//!
58//! ```
59//! # #[macro_use]
60//! # extern crate generic_array;
61//! # extern crate typenum;
62//! # fn main() {
63//! let array = arr![u32; 1, 2, 3];
64//! assert_eq!(array[2], 3);
65//! # }
66//! ```
67
68#![deny(missing_docs)]
69#![deny(meta_variable_misuse)]
70#![no_std]
71#![cfg_attr(docsrs, feature(doc_cfg))]
72#![cfg_attr(
73    ga_is_deprecated,
74    deprecated(note = "please upgrade to generic-array 1.x")
75)]
76
77#[cfg(feature = "serde")]
78extern crate serde;
79
80#[cfg(feature = "zeroize")]
81extern crate zeroize;
82
83#[cfg(test)]
84extern crate bincode;
85
86pub extern crate typenum;
87
88mod hex;
89mod impls;
90
91#[cfg(feature = "serde")]
92mod impl_serde;
93
94#[cfg(feature = "zeroize")]
95mod impl_zeroize;
96
97use core::iter::FromIterator;
98use core::marker::PhantomData;
99use core::mem::{MaybeUninit, ManuallyDrop};
100use core::ops::{Deref, DerefMut};
101use core::{mem, ptr, slice};
102use typenum::bit::{B0, B1};
103use typenum::uint::{UInt, UTerm, Unsigned};
104
105#[cfg_attr(test, macro_use)]
106pub mod arr;
107pub mod functional;
108pub mod iter;
109pub mod sequence;
110
111use self::functional::*;
112pub use self::iter::GenericArrayIter;
113use self::sequence::*;
114
115/// Trait making `GenericArray` work, marking types to be used as length of an array
116pub unsafe trait ArrayLength<T>: Unsigned {
117    /// Associated type representing the array type for the number
118    type ArrayType;
119}
120
121unsafe impl<T> ArrayLength<T> for UTerm {
122    #[doc(hidden)]
123    type ArrayType = [T; 0];
124}
125
126/// Internal type used to generate a struct of appropriate size
127#[allow(dead_code)]
128#[repr(C)]
129#[doc(hidden)]
130pub struct GenericArrayImplEven<T, U> {
131    parent1: U,
132    parent2: U,
133    _marker: PhantomData<T>,
134}
135
136impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
137    fn clone(&self) -> GenericArrayImplEven<T, U> {
138        GenericArrayImplEven {
139            parent1: self.parent1.clone(),
140            parent2: self.parent2.clone(),
141            _marker: PhantomData,
142        }
143    }
144}
145
146impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
147
148/// Internal type used to generate a struct of appropriate size
149#[allow(dead_code)]
150#[repr(C)]
151#[doc(hidden)]
152pub struct GenericArrayImplOdd<T, U> {
153    parent1: U,
154    parent2: U,
155    data: T,
156}
157
158impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
159    fn clone(&self) -> GenericArrayImplOdd<T, U> {
160        GenericArrayImplOdd {
161            parent1: self.parent1.clone(),
162            parent2: self.parent2.clone(),
163            data: self.data.clone(),
164        }
165    }
166}
167
168impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
169
170unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
171    #[doc(hidden)]
172    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
173}
174
175unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
176    #[doc(hidden)]
177    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
178}
179
180/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
181#[allow(dead_code)]
182#[repr(transparent)]
183pub struct GenericArray<T, U: ArrayLength<T>> {
184    data: U::ArrayType,
185}
186
187unsafe impl<T: Send, N: ArrayLength<T>> Send for GenericArray<T, N> {}
188unsafe impl<T: Sync, N: ArrayLength<T>> Sync for GenericArray<T, N> {}
189
190impl<T, N> Deref for GenericArray<T, N>
191where
192    N: ArrayLength<T>,
193{
194    type Target = [T];
195
196    #[inline(always)]
197    fn deref(&self) -> &[T] {
198        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::USIZE) }
199    }
200}
201
202impl<T, N> DerefMut for GenericArray<T, N>
203where
204    N: ArrayLength<T>,
205{
206    #[inline(always)]
207    fn deref_mut(&mut self) -> &mut [T] {
208        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::USIZE) }
209    }
210}
211
212/// Creates an array one element at a time using a mutable iterator
213/// you can write to with `ptr::write`.
214///
215/// Increment the position while iterating to mark off created elements,
216/// which will be dropped if `into_inner` is not called.
217#[doc(hidden)]
218pub struct ArrayBuilder<T, N: ArrayLength<T>> {
219    array: MaybeUninit<GenericArray<T, N>>,
220    position: usize,
221}
222
223impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
224    #[doc(hidden)]
225    #[inline]
226    pub unsafe fn new() -> ArrayBuilder<T, N> {
227        ArrayBuilder {
228            array: MaybeUninit::uninit(),
229            position: 0,
230        }
231    }
232
233    /// Creates a mutable iterator for writing to the array using `ptr::write`.
234    ///
235    /// Increment the position value given as a mutable reference as you iterate
236    /// to mark how many elements have been created.
237    #[doc(hidden)]
238    #[inline]
239    pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {
240        ((&mut *self.array.as_mut_ptr()).iter_mut(), &mut self.position)
241    }
242
243    /// When done writing (assuming all elements have been written to),
244    /// get the inner array.
245    #[doc(hidden)]
246    #[inline]
247    pub unsafe fn into_inner(self) -> GenericArray<T, N> {
248        let array = ptr::read(&self.array);
249
250        mem::forget(self);
251
252        array.assume_init()
253    }
254}
255
256impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
257    fn drop(&mut self) {
258        if mem::needs_drop::<T>() {
259            unsafe {
260                for value in &mut (&mut *self.array.as_mut_ptr())[..self.position] {
261                    ptr::drop_in_place(value);
262                }
263            }
264        }
265    }
266}
267
268/// Consumes an array.
269///
270/// Increment the position while iterating and any leftover elements
271/// will be dropped if position does not go to N
272#[doc(hidden)]
273pub struct ArrayConsumer<T, N: ArrayLength<T>> {
274    array: ManuallyDrop<GenericArray<T, N>>,
275    position: usize,
276}
277
278impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
279    #[doc(hidden)]
280    #[inline]
281    pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
282        ArrayConsumer {
283            array: ManuallyDrop::new(array),
284            position: 0,
285        }
286    }
287
288    /// Creates an iterator and mutable reference to the internal position
289    /// to keep track of consumed elements.
290    ///
291    /// Increment the position as you iterate to mark off consumed elements
292    #[doc(hidden)]
293    #[inline]
294    pub unsafe fn iter_position(&mut self) -> (slice::Iter<T>, &mut usize) {
295        (self.array.iter(), &mut self.position)
296    }
297}
298
299impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
300    fn drop(&mut self) {
301        if mem::needs_drop::<T>() {
302            for value in &mut self.array[self.position..N::USIZE] {
303                unsafe {
304                    ptr::drop_in_place(value);
305                }
306            }
307        }
308    }
309}
310
311impl<'a, T: 'a, N> IntoIterator for &'a GenericArray<T, N>
312where
313    N: ArrayLength<T>,
314{
315    type IntoIter = slice::Iter<'a, T>;
316    type Item = &'a T;
317
318    fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {
319        self.as_slice().iter()
320    }
321}
322
323impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray<T, N>
324where
325    N: ArrayLength<T>,
326{
327    type IntoIter = slice::IterMut<'a, T>;
328    type Item = &'a mut T;
329
330    fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {
331        self.as_mut_slice().iter_mut()
332    }
333}
334
335impl<T, N> FromIterator<T> for GenericArray<T, N>
336where
337    N: ArrayLength<T>,
338{
339    fn from_iter<I>(iter: I) -> GenericArray<T, N>
340    where
341        I: IntoIterator<Item = T>,
342    {
343        unsafe {
344            let mut destination = ArrayBuilder::new();
345
346            {
347                let (destination_iter, position) = destination.iter_position();
348
349                iter.into_iter()
350                    .zip(destination_iter)
351                    .for_each(|(src, dst)| {
352                        ptr::write(dst, src);
353
354                        *position += 1;
355                    });
356            }
357
358            if destination.position < N::USIZE {
359                from_iter_length_fail(destination.position, N::USIZE);
360            }
361
362            destination.into_inner()
363        }
364    }
365}
366
367#[inline(never)]
368#[cold]
369fn from_iter_length_fail(length: usize, expected: usize) -> ! {
370    panic!(
371        "GenericArray::from_iter received {} elements but expected {}",
372        length, expected
373    );
374}
375
376unsafe impl<T, N> GenericSequence<T> for GenericArray<T, N>
377where
378    N: ArrayLength<T>,
379    Self: IntoIterator<Item = T>,
380{
381    type Length = N;
382    type Sequence = Self;
383
384    fn generate<F>(mut f: F) -> GenericArray<T, N>
385    where
386        F: FnMut(usize) -> T,
387    {
388        unsafe {
389            let mut destination = ArrayBuilder::new();
390
391            {
392                let (destination_iter, position) = destination.iter_position();
393
394                destination_iter.enumerate().for_each(|(i, dst)| {
395                    ptr::write(dst, f(i));
396
397                    *position += 1;
398                });
399            }
400
401            destination.into_inner()
402        }
403    }
404
405    #[doc(hidden)]
406    fn inverted_zip<B, U, F>(
407        self,
408        lhs: GenericArray<B, Self::Length>,
409        mut f: F,
410    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
411    where
412        GenericArray<B, Self::Length>:
413            GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
414        Self: MappedGenericSequence<T, U>,
415        Self::Length: ArrayLength<B> + ArrayLength<U>,
416        F: FnMut(B, Self::Item) -> U,
417    {
418        unsafe {
419            let mut left = ArrayConsumer::new(lhs);
420            let mut right = ArrayConsumer::new(self);
421
422            let (left_array_iter, left_position) = left.iter_position();
423            let (right_array_iter, right_position) = right.iter_position();
424
425            FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {
426                let left_value = ptr::read(l);
427                let right_value = ptr::read(r);
428
429                *left_position += 1;
430                *right_position += 1;
431
432                f(left_value, right_value)
433            }))
434        }
435    }
436
437    #[doc(hidden)]
438    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
439    where
440        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
441        Self: MappedGenericSequence<T, U>,
442        Self::Length: ArrayLength<B> + ArrayLength<U>,
443        F: FnMut(Lhs::Item, Self::Item) -> U,
444    {
445        unsafe {
446            let mut right = ArrayConsumer::new(self);
447
448            let (right_array_iter, right_position) = right.iter_position();
449
450            FromIterator::from_iter(
451                lhs.into_iter()
452                    .zip(right_array_iter)
453                    .map(|(left_value, r)| {
454                        let right_value = ptr::read(r);
455
456                        *right_position += 1;
457
458                        f(left_value, right_value)
459                    }),
460            )
461        }
462    }
463}
464
465unsafe impl<T, U, N> MappedGenericSequence<T, U> for GenericArray<T, N>
466where
467    N: ArrayLength<T> + ArrayLength<U>,
468    GenericArray<U, N>: GenericSequence<U, Length = N>,
469{
470    type Mapped = GenericArray<U, N>;
471}
472
473unsafe impl<T, N> FunctionalSequence<T> for GenericArray<T, N>
474where
475    N: ArrayLength<T>,
476    Self: GenericSequence<T, Item = T, Length = N>,
477{
478    fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>
479    where
480        Self::Length: ArrayLength<U>,
481        Self: MappedGenericSequence<T, U>,
482        F: FnMut(T) -> U,
483    {
484        unsafe {
485            let mut source = ArrayConsumer::new(self);
486
487            let (array_iter, position) = source.iter_position();
488
489            FromIterator::from_iter(array_iter.map(|src| {
490                let value = ptr::read(src);
491
492                *position += 1;
493
494                f(value)
495            }))
496        }
497    }
498
499    #[inline]
500    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
501    where
502        Self: MappedGenericSequence<T, U>,
503        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
504        Self::Length: ArrayLength<B> + ArrayLength<U>,
505        Rhs: GenericSequence<B, Length = Self::Length>,
506        F: FnMut(T, Rhs::Item) -> U,
507    {
508        rhs.inverted_zip(self, f)
509    }
510
511    fn fold<U, F>(self, init: U, mut f: F) -> U
512    where
513        F: FnMut(U, T) -> U,
514    {
515        unsafe {
516            let mut source = ArrayConsumer::new(self);
517
518            let (array_iter, position) = source.iter_position();
519
520            array_iter.fold(init, |acc, src| {
521                let value = ptr::read(src);
522
523                *position += 1;
524
525                f(acc, value)
526            })
527        }
528    }
529}
530
531impl<T, N> GenericArray<T, N>
532where
533    N: ArrayLength<T>,
534{
535    /// Extracts a slice containing the entire array.
536    #[inline]
537    pub fn as_slice(&self) -> &[T] {
538        self.deref()
539    }
540
541    /// Extracts a mutable slice containing the entire array.
542    #[inline]
543    pub fn as_mut_slice(&mut self) -> &mut [T] {
544        self.deref_mut()
545    }
546
547    /// Converts slice to a generic array reference with inferred length;
548    ///
549    /// # Panics
550    ///
551    /// Panics if the slice is not equal to the length of the array.
552    #[inline]
553    pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
554        slice.into()
555    }
556
557    /// Converts mutable slice to a mutable generic array reference
558    ///
559    /// # Panics
560    ///
561    /// Panics if the slice is not equal to the length of the array.
562    #[inline]
563    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
564        slice.into()
565    }
566}
567
568impl<'a, T, N: ArrayLength<T>> From<&'a [T]> for &'a GenericArray<T, N> {
569    /// Converts slice to a generic array reference with inferred length;
570    ///
571    /// # Panics
572    ///
573    /// Panics if the slice is not equal to the length of the array.
574    #[inline]
575    fn from(slice: &[T]) -> &GenericArray<T, N> {
576        assert_eq!(slice.len(), N::USIZE);
577
578        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
579    }
580}
581
582impl<'a, T, N: ArrayLength<T>> From<&'a mut [T]> for &'a mut GenericArray<T, N> {
583    /// Converts mutable slice to a mutable generic array reference
584    ///
585    /// # Panics
586    ///
587    /// Panics if the slice is not equal to the length of the array.
588    #[inline]
589    fn from(slice: &mut [T]) -> &mut GenericArray<T, N> {
590        assert_eq!(slice.len(), N::USIZE);
591
592        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
593    }
594}
595
596impl<T: Clone, N> GenericArray<T, N>
597where
598    N: ArrayLength<T>,
599{
600    /// Construct a `GenericArray` from a slice by cloning its content
601    ///
602    /// # Panics
603    ///
604    /// Panics if the slice is not equal to the length of the array.
605    #[inline]
606    pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {
607        Self::from_exact_iter(list.iter().cloned())
608            .expect("Slice must be the same length as the array")
609    }
610}
611
612impl<T, N> GenericArray<T, N>
613where
614    N: ArrayLength<T>,
615{
616    /// Creates a new `GenericArray` instance from an iterator with a specific size.
617    ///
618    /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`.
619    pub fn from_exact_iter<I>(iter: I) -> Option<Self>
620    where
621        I: IntoIterator<Item = T>,
622    {
623        let mut iter = iter.into_iter();
624
625        unsafe {
626            let mut destination = ArrayBuilder::new();
627
628            {
629                let (destination_iter, position) = destination.iter_position();
630
631                destination_iter.zip(&mut iter).for_each(|(dst, src)| {
632                    ptr::write(dst, src);
633
634                    *position += 1;
635                });
636
637                // The iterator produced fewer than `N` elements.
638                if *position != N::USIZE {
639                    return None;
640                }
641
642                // The iterator produced more than `N` elements.
643                if iter.next().is_some() {
644                    return None;
645                }
646            }
647
648            Some(destination.into_inner())
649        }
650    }
651}
652
653/// A reimplementation of the `transmute` function, avoiding problems
654/// when the compiler can't prove equal sizes.
655#[inline]
656#[doc(hidden)]
657pub unsafe fn transmute<A, B>(a: A) -> B {
658    let a = ManuallyDrop::new(a);
659    ::core::ptr::read(&*a as *const A as *const B)
660}
661
662#[cfg(test)]
663mod test {
664    // Compile with:
665    // cargo rustc --lib --profile test --release --
666    //      -C target-cpu=native -C opt-level=3 --emit asm
667    // and view the assembly to make sure test_assembly generates
668    // SIMD instructions instead of a naive loop.
669
670    #[inline(never)]
671    pub fn black_box<T>(val: T) -> T {
672        use core::{mem, ptr};
673
674        let ret = unsafe { ptr::read_volatile(&val) };
675        mem::forget(val);
676        ret
677    }
678
679    #[test]
680    fn test_assembly() {
681        use crate::functional::*;
682
683        let a = black_box(arr![i32; 1, 3, 5, 7]);
684        let b = black_box(arr![i32; 2, 4, 6, 8]);
685
686        let c = (&a).zip(b, |l, r| l + r);
687
688        let d = a.fold(0, |a, x| a + x);
689
690        assert_eq!(c, arr![i32; 3, 7, 11, 15]);
691
692        assert_eq!(d, 16);
693    }
694}