generic-array-0.12.0/.gitignore000064400000000000000000000002231324714114000144720ustar0000000000000000# Compiled files *.o *.so *.rlib *.dll .vscode # Executables *.exe # Generated by Cargo /target/ # We don't pin yet Cargo.lock generic-array-0.12.0/.travis.yml000064400000000000000000000023421314362372200146250ustar0000000000000000language: rust script: - cd $TRAVIS_BUILD_DIR - cargo build - cargo test - cargo build --features serde - cargo test --features serde after_success: |- [ $TRAVIS_BRANCH = master ] && [ $TRAVIS_PULL_REQUEST = false ] && cargo doc && echo "" > target/doc/index.html && sudo pip install ghp-import && ghp-import -n target/doc && git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages env: global: secure: te+DVowxg7YWHJHKRE2eEKEg5lK8IwK4aeKZ6rsDMaTcQFzP+jzSYJiodVuDMXy45sfDMCnkWmVmpfXFI5tCLBSqTDXXOZ0UpE2f4fI0d3inH6McEoXNM43HNZqvEWj6Uc4PzTSzkywcAhg39I08PRbp5zzdj+UhB0Ty++Twwjpipr2KQMNmu9RZEwPtbyjqE69yXkDWy1oM3o51uPnpK0RUH+ZE+B0StTG6CMzVY3gW+kQX96Ow+LYkhgn/YjfubVvKO7QHz8Nd1hOxg78tn1ZTHIazN7p3bJejpsZoU92cNCcx1xM0vV/rXNN1pLxzJOBxNC9tU9FNJAaLsg5kAVGZi8Xvu62nUmkpzki71/nilHBAUxJHGIyv0H52p4DyITEN8NzR5WkqN4qBv814Dpvna1Ua3TPqiYWP/LBb+xM27DuPHKuOifePNWehE84qhQMPgArQyiNCgfKaKbaiFO+J4jiUfEV/1aztuEFyHftLoRYstmHfMkhwYHfSf683QGjlqqoL3SFClp1sKAp8WO5b5ZasT9fOGaqPWi8g28/ZGIu67wocT/hJvXxwozAycsXV36JVHs1ab/ujRYMUbcnObx8E5taKLKhWn2jYWsrJ99bUag7F6wTz1erG0eboScTD8QgVY7Zfvz0Eh1MfePOhEJGZfETR80BypC9fZhY= generic-array-0.12.0/Cargo.toml.orig000064400000000000000000000014761333766306300154210ustar0000000000000000[package] name = "generic-array" version = "0.12.0" authors = [ "Bartłomiej Kamiński ", "Aaron Trent " ] description = "Generic types implementing functionality of arrays" readme = "README.md" license = "MIT" documentation = "http://fizyk20.github.io/generic-array/generic_array/" repository = "https://github.com/fizyk20/generic-array.git" keywords = ["generic", "array"] categories = ["data-structures", "no-std"] [badges] travis-ci = { repository = "fizyk20/generic-array" } [lib] name = "generic_array" [dependencies] typenum = "1.10" serde = { version = "1.0", optional = true, default-features = false } [dev_dependencies] # this can't yet be made optional, see https://github.com/rust-lang/cargo/issues/1596 serde_json = "1.0" bincode = "1.0"generic-array-0.12.0/Cargo.toml0000644000000023730000000000000117060ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "generic-array" version = "0.12.0" authors = ["Bartłomiej Kamiński ", "Aaron Trent "] description = "Generic types implementing functionality of arrays" documentation = "http://fizyk20.github.io/generic-array/generic_array/" readme = "README.md" keywords = ["generic", "array"] categories = ["data-structures", "no-std"] license = "MIT" repository = "https://github.com/fizyk20/generic-array.git" [lib] name = "generic_array" [dependencies.serde] version = "1.0" optional = true default-features = false [dependencies.typenum] version = "1.10" [dev-dependencies.bincode] version = "1.0" [dev-dependencies.serde_json] version = "1.0" [badges.travis-ci] repository = "fizyk20/generic-array" generic-array-0.12.0/CHANGELOG.md000064400000000000000000000042411333766276500143440ustar0000000000000000* **`0.12.0`** * Allow trailing commas in `arr!` macro. * **BREAKING**: Serialize `GenericArray` using `serde` tuples, instead of variable-length sequences. This may not be compatible with old serialized data. * **`0.11.0`** * **BREAKING** Redesign `GenericSequence` with an emphasis on use in generic type parameters. * Add `MappedGenericSequence` and `FunctionalSequence` * Implements optimized `map`, `zip` and `fold` for `GenericArray`, `&GenericArray` and `&mut GenericArray` * **BREAKING** Remove `map_ref`, `zip_ref` and `map_slice` * `map_slice` is now equivalent to `GenericArray::from_iter(slice.iter().map(...))` * **`0.10.0`** * Add `GenericSequence`, `Lengthen`, `Shorten`, `Split` and `Concat` traits. * Redefine `transmute` to avert errors. * **`0.9.0`** * Rewrite construction methods to be well-defined in panic situations, correctly dropping elements. * `NoDrop` crate replaced by `ManuallyDrop` as it became stable in Rust core. * Add optimized `map`/`map_ref` and `zip`/`zip_ref` methods to `GenericArray` * **`0.8.0`** * Implement `AsRef`, `AsMut`, `Borrow`, `BorrowMut`, `Hash` for `GenericArray` * Update `serde` to `1.0` * Update `typenum` * Make macro `arr!` non-cloning * Implement `From<[T; N]>` up to `N=32` * Fix #45 * **`0.7.0`** * Upgrade `serde` to `0.9` * Make `serde` with `no_std` * Implement `PartialOrd`/`Ord` for `GenericArray` * **`0.6.0`** * Fixed #30 * Implement `Default` for `GenericArray` * Implement `LowerHex` and `UpperHex` for `GenericArray` * Use `precision` formatting field in hex representation * Add `as_slice`, `as_mut_slice` * Remove `GenericArray::new` in favor of `Default` trait * Add `from_slice` and `from_mut_slice` * `no_std` and `core` for crate. * **`0.5.0`** * Update `serde` * remove `no_std` feature, fixed #19 * **`0.4.0`** * Re-export `typenum` * **`0.3.0`** * Implement `IntoIter` for `GenericArray` * Add `map` method * Add optional `serde` (de)serialization support feature. * **`< 0.3.0`** * Initial implementation in late 2015 generic-array-0.12.0/LICENSE000064400000000000000000000021231314362372200135160ustar0000000000000000The MIT License (MIT) Copyright (c) 2015 Bartłomiej Kamiński Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.generic-array-0.12.0/README.md000064400000000000000000000022751316122717200137770ustar0000000000000000[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array) [![Build Status](https://travis-ci.org/fizyk20/generic-array.svg?branch=master)](https://travis-ci.org/fizyk20/generic-array) # generic-array This crate implements generic array types for Rust. [Documentation](http://fizyk20.github.io/generic-array/generic_array/) ## Usage The Rust arrays `[T; N]` are problematic in that they can't be used generically with respect to `N`, so for example this won't work: ```rust struct Foo { data: [i32; N] } ``` **generic-array** defines a new trait `ArrayLength` and a struct `GenericArray>`, which let the above be implemented as: ```rust struct Foo> { data: GenericArray } ``` To actually define a type implementing `ArrayLength`, you can use unsigned integer types defined in [typenum](https://github.com/paholg/typenum) crate - for example, `GenericArray` would work almost like `[T; 5]` :) In version 0.1.1 an `arr!` macro was introduced, allowing for creation of arrays as shown below: ```rust let array = arr![u32; 1, 2, 3]; assert_eq!(array[2], 3); ``` generic-array-0.12.0/rustfmt.toml000064400000000000000000000001211331075542100151040ustar0000000000000000reorder_imports = true reorder_imported_names = true use_try_shorthand = true generic-array-0.12.0/src/arr.rs000064400000000000000000000034271333766200100144400ustar0000000000000000//! Implementation for `arr!` macro. use super::ArrayLength; use core::ops::Add; use typenum::U1; /// Helper trait for `arr!` macro pub trait AddLength>: ArrayLength { /// Resulting length type Output: ArrayLength; } impl AddLength for N1 where N1: ArrayLength + Add, N2: ArrayLength, >::Output: ArrayLength, { type Output = >::Output; } /// Helper type for `arr!` macro pub type Inc = >::Output; #[doc(hidden)] #[macro_export] macro_rules! arr_impl { ($T:ty; $N:ty, [$($x:expr),*], []) => ({ unsafe { $crate::transmute::<_, $crate::GenericArray<$T, $N>>([$($x),*]) } }); ($T:ty; $N:ty, [], [$x1:expr]) => ( arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], []) ); ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => ( arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [$($x),+]) ); ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => ( arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], []) ); ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => ( arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [$($x),+]) ); } /// Macro allowing for easy generation of Generic Arrays. /// Example: `let test = arr![u32; 1, 2, 3];` #[macro_export] macro_rules! arr { ($T:ty; $(,)*) => ({ unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) } }); ($T:ty; $($x:expr),* $(,)*) => ( arr_impl!($T; $crate::typenum::U0, [], [$($x),*]) ); ($($x:expr,)+) => (arr![$($x),*]); () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`") } generic-array-0.12.0/src/functional.rs000064400000000000000000000065571326076245500160360ustar0000000000000000//! Functional programming with generic sequences //! //! Please see `tests/generics.rs` for examples of how to best use these in your generic functions. use super::ArrayLength; use core::iter::FromIterator; use sequence::*; /// Defines the relationship between one generic sequence and another, /// for operations such as `map` and `zip`. pub unsafe trait MappedGenericSequence: GenericSequence where Self::Length: ArrayLength, { /// Mapped sequence type type Mapped: GenericSequence; } unsafe impl<'a, T, U, S: MappedGenericSequence> MappedGenericSequence for &'a S where &'a S: GenericSequence, S: GenericSequence>::Length>, >::Length: ArrayLength, { type Mapped = >::Mapped; } unsafe impl<'a, T, U, S: MappedGenericSequence> MappedGenericSequence for &'a mut S where &'a mut S: GenericSequence, S: GenericSequence>::Length>, >::Length: ArrayLength, { type Mapped = >::Mapped; } /// Accessor type for a mapped generic sequence pub type MappedSequence = <>::Mapped as GenericSequence>::Sequence; /// Defines functional programming methods for generic sequences pub unsafe trait FunctionalSequence: GenericSequence { /// Maps a `GenericSequence` to another `GenericSequence`. /// /// If the mapping function panics, any already initialized elements in the new sequence /// will be dropped, AND any unused elements in the source sequence will also be dropped. fn map(self, f: F) -> MappedSequence where Self: MappedGenericSequence, Self::Length: ArrayLength, F: FnMut(Self::Item) -> U, { FromIterator::from_iter(self.into_iter().map(f)) } /// Combines two `GenericSequence` instances and iterates through both of them, /// initializing a new `GenericSequence` with the result of the zipped mapping function. /// /// If the mapping function panics, any already initialized elements in the new sequence /// will be dropped, AND any unused elements in the source sequences will also be dropped. #[inline] fn zip(self, rhs: Rhs, f: F) -> MappedSequence where Self: MappedGenericSequence, Rhs: MappedGenericSequence>, Self::Length: ArrayLength + ArrayLength, Rhs: GenericSequence, F: FnMut(Self::Item, Rhs::Item) -> U, { rhs.inverted_zip2(self, f) } /// Folds (or reduces) a sequence of data into a single value. /// /// If the fold function panics, any unused elements will be dropped. fn fold(self, init: U, f: F) -> U where F: FnMut(U, Self::Item) -> U, { self.into_iter().fold(init, f) } } unsafe impl<'a, T, S: GenericSequence> FunctionalSequence for &'a S where &'a S: GenericSequence, { } unsafe impl<'a, T, S: GenericSequence> FunctionalSequence for &'a mut S where &'a mut S: GenericSequence, { } generic-array-0.12.0/src/hex.rs000064400000000000000000000072471326076245500144550ustar0000000000000000//! Generic array are commonly used as a return value for hash digests, so //! it's a good idea to allow to hexlify them easily. This module implements //! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits. //! //! Example: //! //! ```rust //! # #[macro_use] //! # extern crate generic_array; //! # extern crate typenum; //! # fn main() { //! let array = arr![u8; 10, 20, 30]; //! assert_eq!(format!("{:x}", array), "0a141e"); //! # } //! ``` //! use {ArrayLength, GenericArray}; use core::cmp::min; use core::fmt; use core::ops::Add; use core::str; use typenum::*; static LOWER_CHARS: &'static [u8] = b"0123456789abcdef"; static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF"; impl> fmt::LowerHex for GenericArray where T: Add, >::Output: ArrayLength, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let max_digits = f.precision().unwrap_or_else(|| self.len() * 2); let max_hex = (max_digits >> 1) + (max_digits & 1); if T::to_usize() < 1024 { // For small arrays use a stack allocated // buffer of 2x number of bytes let mut res = GenericArray::>::default(); for (i, c) in self.iter().take(max_hex).enumerate() { res[i * 2] = LOWER_CHARS[(c >> 4) as usize]; res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; } f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; } else { // For large array use chunks of up to 1024 bytes (2048 hex chars) let mut buf = [0u8; 2048]; let mut digits_left = max_digits; for chunk in self[..max_hex].chunks(1024) { for (i, c) in chunk.iter().enumerate() { buf[i * 2] = LOWER_CHARS[(c >> 4) as usize]; buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize]; } let n = min(chunk.len() * 2, digits_left); f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; digits_left -= n; } } Ok(()) } } impl> fmt::UpperHex for GenericArray where T: Add, >::Output: ArrayLength, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let max_digits = f.precision().unwrap_or_else(|| self.len() * 2); let max_hex = (max_digits >> 1) + (max_digits & 1); if T::to_usize() < 1024 { // For small arrays use a stack allocated // buffer of 2x number of bytes let mut res = GenericArray::>::default(); for (i, c) in self.iter().take(max_hex).enumerate() { res[i * 2] = UPPER_CHARS[(c >> 4) as usize]; res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; } f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?; } else { // For large array use chunks of up to 1024 bytes (2048 hex chars) let mut buf = [0u8; 2048]; let mut digits_left = max_digits; for chunk in self[..max_hex].chunks(1024) { for (i, c) in chunk.iter().enumerate() { buf[i * 2] = UPPER_CHARS[(c >> 4) as usize]; buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize]; } let n = min(chunk.len() * 2, digits_left); f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?; digits_left -= n; } } Ok(()) } } generic-array-0.12.0/src/impl_serde.rs000064400000000000000000000054511333766200100157760ustar0000000000000000//! Serde serialization/deserialization implementation use core::fmt; use core::marker::PhantomData; use serde::de::{self, SeqAccess, Visitor}; use serde::{ser::SerializeTuple, Deserialize, Deserializer, Serialize, Serializer}; use {ArrayLength, GenericArray}; impl Serialize for GenericArray where T: Serialize, N: ArrayLength, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut tup = serializer.serialize_tuple(N::to_usize())?; for el in self { tup.serialize_element(el)?; } tup.end() } } struct GAVisitor { _t: PhantomData, _n: PhantomData, } impl<'de, T, N> Visitor<'de> for GAVisitor where T: Deserialize<'de> + Default, N: ArrayLength, { type Value = GenericArray; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct GenericArray") } fn visit_seq(self, mut seq: A) -> Result, A::Error> where A: SeqAccess<'de>, { let mut result = GenericArray::default(); for i in 0..N::to_usize() { result[i] = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(i, &self))?; } Ok(result) } } impl<'de, T, N> Deserialize<'de> for GenericArray where T: Deserialize<'de> + Default, N: ArrayLength, { fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let visitor = GAVisitor { _t: PhantomData, _n: PhantomData, }; deserializer.deserialize_tuple(N::to_usize(), visitor) } } #[cfg(test)] mod tests { use super::*; use bincode; use typenum; #[test] fn test_serialize() { let array = GenericArray::::default(); let serialized = bincode::serialize(&array); assert!(serialized.is_ok()); } #[test] fn test_deserialize() { let mut array = GenericArray::::default(); array[0] = 1; array[1] = 2; let serialized = bincode::serialize(&array).unwrap(); let deserialized = bincode::deserialize::>(&array); assert!(deserialized.is_ok()); let array = deserialized.unwrap(); assert_eq!(array[0], 1); assert_eq!(array[1], 2); } #[test] fn test_serialized_size() { let array = GenericArray::::default(); let size = bincode::serialized_size(&array).unwrap(); assert_eq!(size, 1); } } generic-array-0.12.0/src/impls.rs000064400000000000000000000071271326076245500150120ustar0000000000000000use super::{ArrayLength, GenericArray}; use core::borrow::{Borrow, BorrowMut}; use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; use functional::*; use sequence::*; impl Default for GenericArray where N: ArrayLength, { #[inline] fn default() -> Self { Self::generate(|_| T::default()) } } impl Clone for GenericArray where N: ArrayLength, { fn clone(&self) -> GenericArray { self.map(|x| x.clone()) } } impl Copy for GenericArray where N: ArrayLength, N::ArrayType: Copy, { } impl PartialEq for GenericArray where N: ArrayLength, { fn eq(&self, other: &Self) -> bool { **self == **other } } impl Eq for GenericArray where N: ArrayLength, { } impl PartialOrd for GenericArray where N: ArrayLength, { fn partial_cmp(&self, other: &GenericArray) -> Option { PartialOrd::partial_cmp(self.as_slice(), other.as_slice()) } } impl Ord for GenericArray where N: ArrayLength, { fn cmp(&self, other: &GenericArray) -> Ordering { Ord::cmp(self.as_slice(), other.as_slice()) } } impl Debug for GenericArray where N: ArrayLength, { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self[..].fmt(fmt) } } impl Borrow<[T]> for GenericArray where N: ArrayLength, { fn borrow(&self) -> &[T] { &self[..] } } impl BorrowMut<[T]> for GenericArray where N: ArrayLength, { fn borrow_mut(&mut self) -> &mut [T] { &mut self[..] } } impl AsRef<[T]> for GenericArray where N: ArrayLength, { fn as_ref(&self) -> &[T] { &self[..] } } impl AsMut<[T]> for GenericArray where N: ArrayLength, { fn as_mut(&mut self) -> &mut [T] { &mut self[..] } } impl Hash for GenericArray where N: ArrayLength, { fn hash(&self, state: &mut H) where H: Hasher, { Hash::hash(&self[..], state) } } macro_rules! impl_from { ($($n: expr => $ty: ty),*) => { $( impl From<[T; $n]> for GenericArray { fn from(arr: [T; $n]) -> Self { use core::mem::{forget, transmute_copy}; let x = unsafe { transmute_copy(&arr) }; forget(arr); x } } )* } } impl_from! { 1 => ::typenum::U1, 2 => ::typenum::U2, 3 => ::typenum::U3, 4 => ::typenum::U4, 5 => ::typenum::U5, 6 => ::typenum::U6, 7 => ::typenum::U7, 8 => ::typenum::U8, 9 => ::typenum::U9, 10 => ::typenum::U10, 11 => ::typenum::U11, 12 => ::typenum::U12, 13 => ::typenum::U13, 14 => ::typenum::U14, 15 => ::typenum::U15, 16 => ::typenum::U16, 17 => ::typenum::U17, 18 => ::typenum::U18, 19 => ::typenum::U19, 20 => ::typenum::U20, 21 => ::typenum::U21, 22 => ::typenum::U22, 23 => ::typenum::U23, 24 => ::typenum::U24, 25 => ::typenum::U25, 26 => ::typenum::U26, 27 => ::typenum::U27, 28 => ::typenum::U28, 29 => ::typenum::U29, 30 => ::typenum::U30, 31 => ::typenum::U31, 32 => ::typenum::U32 } generic-array-0.12.0/src/iter.rs000064400000000000000000000110451326076245500146230ustar0000000000000000//! `GenericArray` iterator implementation. use super::{ArrayLength, GenericArray}; use core::{cmp, ptr, fmt, mem}; use core::mem::ManuallyDrop; /// An iterator that moves out of a `GenericArray` pub struct GenericArrayIter> { // Invariants: index <= index_back <= N // Only values in array[index..index_back] are alive at any given time. // Values from array[..index] and array[index_back..] are already moved/dropped. array: ManuallyDrop>, index: usize, index_back: usize, } #[cfg(test)] mod test { use super::*; fn send(_iter: I) {} #[test] fn test_send_iter() { send(GenericArray::from([1, 2, 3, 4]).into_iter()); } } impl GenericArrayIter where N: ArrayLength, { /// Returns the remaining items of this iterator as a slice #[inline] pub fn as_slice(&self) -> &[T] { &self.array.as_slice()[self.index..self.index_back] } /// Returns the remaining items of this iterator as a mutable slice #[inline] pub fn as_mut_slice(&mut self) -> &mut [T] { &mut self.array.as_mut_slice()[self.index..self.index_back] } } impl IntoIterator for GenericArray where N: ArrayLength, { type Item = T; type IntoIter = GenericArrayIter; fn into_iter(self) -> Self::IntoIter { GenericArrayIter { array: ManuallyDrop::new(self), index: 0, index_back: N::to_usize(), } } } // Based on work in rust-lang/rust#49000 impl fmt::Debug for GenericArrayIter where N: ArrayLength, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("GenericArrayIter") .field(&self.as_slice()) .finish() } } impl Drop for GenericArrayIter where N: ArrayLength, { #[inline] fn drop(&mut self) { // Drop values that are still alive. for p in self.as_mut_slice() { unsafe { ptr::drop_in_place(p); } } } } // Based on work in rust-lang/rust#49000 impl Clone for GenericArrayIter where N: ArrayLength, { fn clone(&self) -> Self { // This places all cloned elements at the start of the new array iterator, // not at their original indices. unsafe { let mut iter = GenericArrayIter { array: ManuallyDrop::new(mem::uninitialized()), index: 0, index_back: 0, }; for (dst, src) in iter.array.iter_mut().zip(self.as_slice()) { ptr::write(dst, src.clone()); iter.index_back += 1; } iter } } } impl Iterator for GenericArrayIter where N: ArrayLength, { type Item = T; #[inline] fn next(&mut self) -> Option { if self.index < self.index_back { let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) }; self.index += 1; p } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } #[inline] fn count(self) -> usize { self.len() } fn nth(&mut self, n: usize) -> Option { // First consume values prior to the nth. let ndrop = cmp::min(n, self.len()); for p in &mut self.array[self.index..self.index + ndrop] { self.index += 1; unsafe { ptr::drop_in_place(p); } } self.next() } fn last(mut self) -> Option { // Note, everything else will correctly drop first as `self` leaves scope. self.next_back() } } impl DoubleEndedIterator for GenericArrayIter where N: ArrayLength, { fn next_back(&mut self) -> Option { if self.index < self.index_back { self.index_back -= 1; unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) } } else { None } } } impl ExactSizeIterator for GenericArrayIter where N: ArrayLength, { fn len(&self) -> usize { self.index_back - self.index } } // TODO: Implement `FusedIterator` and `TrustedLen` when stabilizedgeneric-array-0.12.0/src/lib.rs000064400000000000000000000420701333766200100144170ustar0000000000000000//! This crate implements a structure that can be used as a generic array type.use //! Core Rust array types `[T; N]` can't be used generically with //! respect to `N`, so for example this: //! //! ```{should_fail} //! struct Foo { //! data: [T; N] //! } //! ``` //! //! won't work. //! //! **generic-array** exports a `GenericArray` type, which lets //! the above be implemented as: //! //! ``` //! # use generic_array::{ArrayLength, GenericArray}; //! struct Foo> { //! data: GenericArray //! } //! ``` //! //! The `ArrayLength` trait is implemented by default for //! [unsigned integer types](../typenum/uint/index.html) from //! [typenum](../typenum/index.html). //! //! For ease of use, an `arr!` macro is provided - example below: //! //! ``` //! # #[macro_use] //! # extern crate generic_array; //! # extern crate typenum; //! # fn main() { //! let array = arr![u32; 1, 2, 3]; //! assert_eq!(array[2], 3); //! # } //! ``` #![deny(missing_docs)] #![no_std] #[cfg(feature = "serde")] extern crate serde; #[cfg(test)] extern crate bincode; pub extern crate typenum; mod hex; mod impls; #[cfg(feature = "serde")] pub mod impl_serde; use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::ManuallyDrop; use core::ops::{Deref, DerefMut}; use core::{mem, ptr, slice}; use typenum::bit::{B0, B1}; use typenum::uint::{UInt, UTerm, Unsigned}; #[cfg_attr(test, macro_use)] pub mod arr; pub mod functional; pub mod iter; pub mod sequence; use functional::*; pub use iter::GenericArrayIter; use sequence::*; /// Trait making `GenericArray` work, marking types to be used as length of an array pub unsafe trait ArrayLength: Unsigned { /// Associated type representing the array type for the number type ArrayType; } unsafe impl ArrayLength for UTerm { #[doc(hidden)] type ArrayType = (); } /// Internal type used to generate a struct of appropriate size #[allow(dead_code)] #[repr(C)] #[doc(hidden)] pub struct GenericArrayImplEven { parent1: U, parent2: U, _marker: PhantomData, } impl Clone for GenericArrayImplEven { fn clone(&self) -> GenericArrayImplEven { GenericArrayImplEven { parent1: self.parent1.clone(), parent2: self.parent2.clone(), _marker: PhantomData, } } } impl Copy for GenericArrayImplEven {} /// Internal type used to generate a struct of appropriate size #[allow(dead_code)] #[repr(C)] #[doc(hidden)] pub struct GenericArrayImplOdd { parent1: U, parent2: U, data: T, } impl Clone for GenericArrayImplOdd { fn clone(&self) -> GenericArrayImplOdd { GenericArrayImplOdd { parent1: self.parent1.clone(), parent2: self.parent2.clone(), data: self.data.clone(), } } } impl Copy for GenericArrayImplOdd {} unsafe impl> ArrayLength for UInt { #[doc(hidden)] type ArrayType = GenericArrayImplEven; } unsafe impl> ArrayLength for UInt { #[doc(hidden)] type ArrayType = GenericArrayImplOdd; } /// Struct representing a generic array - `GenericArray` works like [T; N] #[allow(dead_code)] pub struct GenericArray> { data: U::ArrayType, } unsafe impl> Send for GenericArray {} unsafe impl> Sync for GenericArray {} impl Deref for GenericArray where N: ArrayLength, { type Target = [T]; fn deref(&self) -> &[T] { unsafe { slice::from_raw_parts(self as *const Self as *const T, N::to_usize()) } } } impl DerefMut for GenericArray where N: ArrayLength, { fn deref_mut(&mut self) -> &mut [T] { unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize()) } } } /// Creates an array one element at a time using a mutable iterator /// you can write to with `ptr::write`. /// /// Incremenent the position while iterating to mark off created elements, /// which will be dropped if `into_inner` is not called. #[doc(hidden)] pub struct ArrayBuilder> { array: ManuallyDrop>, position: usize, } impl> ArrayBuilder { #[doc(hidden)] #[inline] pub unsafe fn new() -> ArrayBuilder { ArrayBuilder { array: ManuallyDrop::new(mem::uninitialized()), position: 0, } } /// Creates a mutable iterator for writing to the array using `ptr::write`. /// /// Increment the position value given as a mutable reference as you iterate /// to mark how many elements have been created. #[doc(hidden)] #[inline] pub unsafe fn iter_position(&mut self) -> (slice::IterMut, &mut usize) { (self.array.iter_mut(), &mut self.position) } /// When done writing (assuming all elements have been written to), /// get the inner array. #[doc(hidden)] #[inline] pub unsafe fn into_inner(self) -> GenericArray { let array = ptr::read(&self.array); mem::forget(self); ManuallyDrop::into_inner(array) } } impl> Drop for ArrayBuilder { fn drop(&mut self) { for value in &mut self.array[..self.position] { unsafe { ptr::drop_in_place(value); } } } } /// Consumes an array. /// /// Increment the position while iterating and any leftover elements /// will be dropped if position does not go to N #[doc(hidden)] pub struct ArrayConsumer> { array: ManuallyDrop>, position: usize, } impl> ArrayConsumer { #[doc(hidden)] #[inline] pub unsafe fn new(array: GenericArray) -> ArrayConsumer { ArrayConsumer { array: ManuallyDrop::new(array), position: 0, } } /// Creates an iterator and mutable reference to the internal position /// to keep track of consumed elements. /// /// Increment the position as you iterate to mark off consumed elements #[doc(hidden)] #[inline] pub unsafe fn iter_position(&mut self) -> (slice::Iter, &mut usize) { (self.array.iter(), &mut self.position) } } impl> Drop for ArrayConsumer { fn drop(&mut self) { for value in &mut self.array[self.position..N::to_usize()] { unsafe { ptr::drop_in_place(value); } } } } impl<'a, T: 'a, N> IntoIterator for &'a GenericArray where N: ArrayLength, { type IntoIter = slice::Iter<'a, T>; type Item = &'a T; fn into_iter(self: &'a GenericArray) -> Self::IntoIter { self.as_slice().iter() } } impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray where N: ArrayLength, { type IntoIter = slice::IterMut<'a, T>; type Item = &'a mut T; fn into_iter(self: &'a mut GenericArray) -> Self::IntoIter { self.as_mut_slice().iter_mut() } } impl FromIterator for GenericArray where N: ArrayLength, { fn from_iter(iter: I) -> GenericArray where I: IntoIterator, { unsafe { let mut destination = ArrayBuilder::new(); { let (destination_iter, position) = destination.iter_position(); for (src, dst) in iter.into_iter().zip(destination_iter) { ptr::write(dst, src); *position += 1; } } if destination.position < N::to_usize() { from_iter_length_fail(destination.position, N::to_usize()); } destination.into_inner() } } } #[inline(never)] #[cold] fn from_iter_length_fail(length: usize, expected: usize) -> ! { panic!( "GenericArray::from_iter received {} elements but expected {}", length, expected ); } unsafe impl GenericSequence for GenericArray where N: ArrayLength, Self: IntoIterator, { type Length = N; type Sequence = Self; fn generate(mut f: F) -> GenericArray where F: FnMut(usize) -> T, { unsafe { let mut destination = ArrayBuilder::new(); { let (destination_iter, position) = destination.iter_position(); for (i, dst) in destination_iter.enumerate() { ptr::write(dst, f(i)); *position += 1; } } destination.into_inner() } } #[doc(hidden)] fn inverted_zip( self, lhs: GenericArray, mut f: F, ) -> MappedSequence, B, U> where GenericArray: GenericSequence + MappedGenericSequence, Self: MappedGenericSequence, Self::Length: ArrayLength + ArrayLength, F: FnMut(B, Self::Item) -> U, { unsafe { let mut left = ArrayConsumer::new(lhs); let mut right = ArrayConsumer::new(self); let (left_array_iter, left_position) = left.iter_position(); let (right_array_iter, right_position) = right.iter_position(); FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| { let left_value = ptr::read(l); let right_value = ptr::read(r); *left_position += 1; *right_position += 1; f(left_value, right_value) })) } } #[doc(hidden)] fn inverted_zip2(self, lhs: Lhs, mut f: F) -> MappedSequence where Lhs: GenericSequence + MappedGenericSequence, Self: MappedGenericSequence, Self::Length: ArrayLength + ArrayLength, F: FnMut(Lhs::Item, Self::Item) -> U, { unsafe { let mut right = ArrayConsumer::new(self); let (right_array_iter, right_position) = right.iter_position(); FromIterator::from_iter( lhs.into_iter() .zip(right_array_iter) .map(|(left_value, r)| { let right_value = ptr::read(r); *right_position += 1; f(left_value, right_value) }), ) } } } unsafe impl MappedGenericSequence for GenericArray where N: ArrayLength + ArrayLength, GenericArray: GenericSequence, { type Mapped = GenericArray; } unsafe impl FunctionalSequence for GenericArray where N: ArrayLength, Self: GenericSequence, { fn map(self, mut f: F) -> MappedSequence where Self::Length: ArrayLength, Self: MappedGenericSequence, F: FnMut(T) -> U, { unsafe { let mut source = ArrayConsumer::new(self); let (array_iter, position) = source.iter_position(); FromIterator::from_iter(array_iter.map(|src| { let value = ptr::read(src); *position += 1; f(value) })) } } #[inline] fn zip(self, rhs: Rhs, f: F) -> MappedSequence where Self: MappedGenericSequence, Rhs: MappedGenericSequence>, Self::Length: ArrayLength + ArrayLength, Rhs: GenericSequence, F: FnMut(T, Rhs::Item) -> U, { rhs.inverted_zip(self, f) } fn fold(self, init: U, mut f: F) -> U where F: FnMut(U, T) -> U, { unsafe { let mut source = ArrayConsumer::new(self); let (array_iter, position) = source.iter_position(); array_iter.fold(init, |acc, src| { let value = ptr::read(src); *position += 1; f(acc, value) }) } } } impl GenericArray where N: ArrayLength, { /// Extracts a slice containing the entire array. #[inline] pub fn as_slice(&self) -> &[T] { self.deref() } /// Extracts a mutable slice containing the entire array. #[inline] pub fn as_mut_slice(&mut self) -> &mut [T] { self.deref_mut() } /// Converts slice to a generic array reference with inferred length; /// /// Length of the slice must be equal to the length of the array. #[inline] pub fn from_slice(slice: &[T]) -> &GenericArray { slice.into() } /// Converts mutable slice to a mutable generic array reference /// /// Length of the slice must be equal to the length of the array. #[inline] pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray { slice.into() } } impl<'a, T, N: ArrayLength> From<&'a [T]> for &'a GenericArray { /// Converts slice to a generic array reference with inferred length; /// /// Length of the slice must be equal to the length of the array. #[inline] fn from(slice: &[T]) -> &GenericArray { assert_eq!(slice.len(), N::to_usize()); unsafe { &*(slice.as_ptr() as *const GenericArray) } } } impl<'a, T, N: ArrayLength> From<&'a mut [T]> for &'a mut GenericArray { /// Converts mutable slice to a mutable generic array reference /// /// Length of the slice must be equal to the length of the array. #[inline] fn from(slice: &mut [T]) -> &mut GenericArray { assert_eq!(slice.len(), N::to_usize()); unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray) } } } impl GenericArray where N: ArrayLength, { /// Construct a `GenericArray` from a slice by cloning its content /// /// Length of the slice must be equal to the length of the array #[inline] pub fn clone_from_slice(list: &[T]) -> GenericArray { Self::from_exact_iter(list.iter().cloned()) .expect("Slice must be the same length as the array") } } impl GenericArray where N: ArrayLength, { /// Creates a new `GenericArray` instance from an iterator with a known exact size. /// /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`. pub fn from_exact_iter(iter: I) -> Option where I: IntoIterator, ::IntoIter: ExactSizeIterator, { let iter = iter.into_iter(); if iter.len() == N::to_usize() { unsafe { let mut destination = ArrayBuilder::new(); { let (destination_iter, position) = destination.iter_position(); for (dst, src) in destination_iter.zip(iter.into_iter()) { ptr::write(dst, src); *position += 1; } } Some(destination.into_inner()) } } else { None } } } /// A reimplementation of the `transmute` function, avoiding problems /// when the compiler can't prove equal sizes. #[inline] #[doc(hidden)] pub unsafe fn transmute(a: A) -> B { let b = ::core::ptr::read(&a as *const A as *const B); ::core::mem::forget(a); b } #[cfg(test)] mod test { // Compile with: // cargo rustc --lib --profile test --release -- // -C target-cpu=native -C opt-level=3 --emit asm // and view the assembly to make sure test_assembly generates // SIMD instructions instead of a niave loop. #[inline(never)] pub fn black_box(val: T) -> T { use core::{mem, ptr}; let ret = unsafe { ptr::read_volatile(&val) }; mem::forget(val); ret } #[test] fn test_assembly() { use functional::*; let a = black_box(arr![i32; 1, 3, 5, 7]); let b = black_box(arr![i32; 2, 4, 6, 8]); let c = (&a).zip(b, |l, r| l + r); let d = a.fold(0, |a, x| a + x); assert_eq!(c, arr![i32; 3, 7, 11, 15]); assert_eq!(d, 16); } } generic-array-0.12.0/src/sequence.rs000064400000000000000000000225461326076540500154760ustar0000000000000000//! Useful traits for manipulating sequences of data stored in `GenericArray`s use super::*; use core::{mem, ptr}; use core::ops::{Add, Sub}; use typenum::operator_aliases::*; /// Defines some sequence with an associated length and iteration capabilities. /// /// This is useful for passing N-length generic arrays as generics. pub unsafe trait GenericSequence: Sized + IntoIterator { /// `GenericArray` associated length type Length: ArrayLength; /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence` type Sequence: GenericSequence + FromIterator; /// Initializes a new sequence instance using the given function. /// /// If the generator function panics while initializing the sequence, /// any already initialized elements will be dropped. fn generate(f: F) -> Self::Sequence where F: FnMut(usize) -> T; #[doc(hidden)] fn inverted_zip( self, lhs: GenericArray, mut f: F, ) -> MappedSequence, B, U> where GenericArray: GenericSequence + MappedGenericSequence, Self: MappedGenericSequence, Self::Length: ArrayLength + ArrayLength, F: FnMut(B, Self::Item) -> U, { unsafe { let mut left = ArrayConsumer::new(lhs); let (left_array_iter, left_position) = left.iter_position(); FromIterator::from_iter( left_array_iter .zip(self.into_iter()) .map(|(l, right_value)| { let left_value = ptr::read(l); *left_position += 1; f(left_value, right_value) }) ) } } #[doc(hidden)] fn inverted_zip2(self, lhs: Lhs, mut f: F) -> MappedSequence where Lhs: GenericSequence + MappedGenericSequence, Self: MappedGenericSequence, Self::Length: ArrayLength + ArrayLength, F: FnMut(Lhs::Item, Self::Item) -> U, { FromIterator::from_iter(lhs.into_iter().zip(self.into_iter()).map(|(l, r)| f(l, r))) } } /// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item` /// /// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`, /// this can be useful for keeping things organized. pub type SequenceItem = ::Item; unsafe impl<'a, T: 'a, S: GenericSequence> GenericSequence for &'a S where &'a S: IntoIterator, { type Length = S::Length; type Sequence = S::Sequence; #[inline] fn generate(f: F) -> Self::Sequence where F: FnMut(usize) -> T, { S::generate(f) } } unsafe impl<'a, T: 'a, S: GenericSequence> GenericSequence for &'a mut S where &'a mut S: IntoIterator, { type Length = S::Length; type Sequence = S::Sequence; #[inline] fn generate(f: F) -> Self::Sequence where F: FnMut(usize) -> T, { S::generate(f) } } /// Defines any `GenericSequence` which can be lengthened or extended by appending /// or prepending an element to it. /// /// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back` pub unsafe trait Lengthen: Sized + GenericSequence { /// `GenericSequence` that has one more element than `Self` type Longer: Shorten; /// Returns a new array with the given element appended to the end of it. /// /// Example: /// /// ```ignore /// let a = arr![i32; 1, 2, 3]; /// /// let b = a.append(4); /// /// assert_eq!(b, arr![i32; 1, 2, 3, 4]); /// ``` fn append(self, last: T) -> Self::Longer; /// Returns a new array with the given element prepended to the front of it. /// /// Example: /// /// ```ignore /// let a = arr![i32; 1, 2, 3]; /// /// let b = a.prepend(4); /// /// assert_eq!(b, arr![i32; 4, 1, 2, 3]); /// ``` fn prepend(self, first: T) -> Self::Longer; } /// Defines a `GenericSequence` which can be shortened by removing the first or last element from it. /// /// Additionally, any shortened sequence can be lengthened by /// appending or prepending an element to it. pub unsafe trait Shorten: Sized + GenericSequence { /// `GenericSequence` that has one less element than `Self` type Shorter: Lengthen; /// Returns a new array without the last element, and the last element. /// /// Example: /// /// ```ignore /// let a = arr![i32; 1, 2, 3, 4]; /// /// let (init, last) = a.pop_back(); /// /// assert_eq!(init, arr![i32; 1, 2, 3]); /// assert_eq!(last, 4); /// ``` fn pop_back(self) -> (Self::Shorter, T); /// Returns a new array without the first element, and the first element. /// Example: /// /// ```ignore /// let a = arr![i32; 1, 2, 3, 4]; /// /// let (head, tail) = a.pop_front(); /// /// assert_eq!(head, 1); /// assert_eq!(tail, arr![i32; 2, 3, 4]); /// ``` fn pop_front(self) -> (T, Self::Shorter); } unsafe impl> Lengthen for GenericArray where N: Add, Add1: ArrayLength, Add1: Sub, Sub1>: ArrayLength, { type Longer = GenericArray>; fn append(self, last: T) -> Self::Longer { let mut longer: Self::Longer = unsafe { mem::uninitialized() }; unsafe { ptr::write(longer.as_mut_ptr() as *mut _, self); ptr::write(&mut longer[N::to_usize()], last); } longer } fn prepend(self, first: T) -> Self::Longer { let mut longer: Self::Longer = unsafe { mem::uninitialized() }; let longer_ptr = longer.as_mut_ptr(); unsafe { ptr::write(longer_ptr as *mut _, first); ptr::write(longer_ptr.offset(1) as *mut _, self); } longer } } unsafe impl> Shorten for GenericArray where N: Sub, Sub1: ArrayLength, Sub1: Add, Add1>: ArrayLength, { type Shorter = GenericArray>; fn pop_back(self) -> (Self::Shorter, T) { let init_ptr = self.as_ptr(); let last_ptr = unsafe { init_ptr.offset(Sub1::::to_usize() as isize) }; let init = unsafe { ptr::read(init_ptr as _) }; let last = unsafe { ptr::read(last_ptr as _) }; mem::forget(self); (init, last) } fn pop_front(self) -> (T, Self::Shorter) { let head_ptr = self.as_ptr(); let tail_ptr = unsafe { head_ptr.offset(1) }; let head = unsafe { ptr::read(head_ptr as _) }; let tail = unsafe { ptr::read(tail_ptr as _) }; mem::forget(self); (head, tail) } } /// Defines a `GenericSequence` that can be split into two parts at a given pivot index. pub unsafe trait Split: GenericSequence where K: ArrayLength, { /// First part of the resulting split array type First: GenericSequence; /// Second part of the resulting split array type Second: GenericSequence; /// Splits an array at the given index, returning the separate parts of the array. fn split(self) -> (Self::First, Self::Second); } unsafe impl Split for GenericArray where N: ArrayLength, K: ArrayLength, N: Sub, Diff: ArrayLength, { type First = GenericArray; type Second = GenericArray>; fn split(self) -> (Self::First, Self::Second) { let head_ptr = self.as_ptr(); let tail_ptr = unsafe { head_ptr.offset(K::to_usize() as isize) }; let head = unsafe { ptr::read(head_ptr as _) }; let tail = unsafe { ptr::read(tail_ptr as _) }; mem::forget(self); (head, tail) } } /// Defines `GenericSequence`s which can be joined together, forming a larger array. pub unsafe trait Concat: GenericSequence where M: ArrayLength, { /// Sequence to be concatenated with `self` type Rest: GenericSequence; /// Resulting sequence formed by the concatenation. type Output: GenericSequence; /// Concatenate, or join, two sequences. fn concat(self, rest: Self::Rest) -> Self::Output; } unsafe impl Concat for GenericArray where N: ArrayLength + Add, M: ArrayLength, Sum: ArrayLength, { type Rest = GenericArray; type Output = GenericArray>; fn concat(self, rest: Self::Rest) -> Self::Output { let mut output: Self::Output = unsafe { mem::uninitialized() }; let output_ptr = output.as_mut_ptr(); unsafe { ptr::write(output_ptr as *mut _, self); ptr::write(output_ptr.offset(N::to_usize() as isize) as *mut _, rest); } output } } generic-array-0.12.0/tests/arr.rs000064400000000000000000000010601333766200100150020ustar0000000000000000#[macro_use] extern crate generic_array; extern crate typenum; #[test] fn empty_without_trailing_comma() { let ar = arr![u8; ]; assert_eq!(format!("{:x}", ar), ""); } #[test] fn empty_with_trailing_comma() { let ar = arr![u8; , ]; assert_eq!(format!("{:x}", ar), ""); } #[test] fn without_trailing_comma() { let ar = arr![u8; 10, 20, 30]; assert_eq!(format!("{:x}", ar), "0a141e"); } #[test] fn with_trailing_comma() { let ar = arr![u8; 10, 20, 30, ]; assert_eq!(format!("{:x}", ar), "0a141e"); } generic-array-0.12.0/tests/generics.rs000064400000000000000000000100401326076245500160240ustar0000000000000000#![recursion_limit = "128"] #[macro_use] extern crate generic_array; use generic_array::typenum::consts::U4; use std::fmt::Debug; use std::ops::Add; use generic_array::{GenericArray, ArrayLength}; use generic_array::sequence::*; use generic_array::functional::*; /// Example function using generics to pass N-length sequences and map them pub fn generic_map(s: S) where S: FunctionalSequence, // `.map` S::Item: Add, // `x + 1` S: MappedGenericSequence, // `i32` -> `i32` MappedSequence: Debug, // println! { let a = s.map(|x| x + 1); println!("{:?}", a); } /// Complex example function using generics to pass N-length sequences, zip them, and then map that result. /// /// If used with `GenericArray` specifically this isn't necessary pub fn generic_sequence_zip_sum(a: A, b: B) -> i32 where A: FunctionalSequence, // `.zip` B: FunctionalSequence, // `.zip` A: MappedGenericSequence, // `i32` -> `i32` B: MappedGenericSequence>, // `i32` -> `i32`, prove A and B can map to the same output A::Item: Add, // `l + r` MappedSequence: MappedGenericSequence + FunctionalSequence, // `.map` SequenceItem>: Add, // `x + 1` MappedSequence, i32, i32>: Debug, // `println!` MappedSequence, i32, i32>: FunctionalSequence, // `.fold` SequenceItem, i32, i32>>: Add // `x + a`, note the order { let c = a.zip(b, |l, r| l + r).map(|x| x + 1); println!("{:?}", c); c.fold(0, |a, x| x + a) } /// Super-simple fixed-length i32 `GenericArray`s pub fn generic_array_plain_zip_sum(a: GenericArray, b: GenericArray) -> i32 { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } pub fn generic_array_variable_length_zip_sum(a: GenericArray, b: GenericArray) -> i32 where N: ArrayLength, { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } pub fn generic_array_same_type_variable_length_zip_sum(a: GenericArray, b: GenericArray) -> i32 where N: ArrayLength + ArrayLength<>::Output>, T: Add, { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } /// Complex example using fully generic `GenericArray`s with the same length. /// /// It's mostly just the repeated `Add` traits, which would be present in other systems anyway. pub fn generic_array_zip_sum + ArrayLength>(a: GenericArray, b: GenericArray) -> i32 where A: Add, N: ArrayLength<>::Output> + ArrayLength<<>::Output as Add>::Output>, >::Output: Add, <>::Output as Add>::Output: Add, { a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a) } #[test] fn test_generics() { generic_map(arr![i32; 1, 2, 3, 4]); assert_eq!(generic_sequence_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_plain_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_same_type_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); assert_eq!(generic_array_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28); }generic-array-0.12.0/tests/hex.rs000064400000000000000000000031411326076245500150150ustar0000000000000000#[macro_use] extern crate generic_array; extern crate typenum; use generic_array::GenericArray; use std::str::from_utf8; use typenum::U2048; #[test] fn short_lower_hex() { let ar = arr![u8; 10, 20, 30]; assert_eq!(format!("{:x}", ar), "0a141e"); } #[test] fn short_upper_hex() { let ar = arr![u8; 30, 20, 10]; assert_eq!(format!("{:X}", ar), "1E140A"); } #[test] fn long_lower_hex() { let ar = GenericArray::::default(); assert_eq!(format!("{:x}", ar), from_utf8(&[b'0'; 4096]).unwrap()); } #[test] fn long_lower_hex_truncated() { let ar = GenericArray::::default(); assert_eq!(format!("{:.3001x}", ar), from_utf8(&[b'0'; 3001]).unwrap()); } #[test] fn long_upper_hex() { let ar = GenericArray::::default(); assert_eq!(format!("{:X}", ar), from_utf8(&[b'0'; 4096]).unwrap()); } #[test] fn long_upper_hex_truncated() { let ar = GenericArray::::default(); assert_eq!(format!("{:.2777X}", ar), from_utf8(&[b'0'; 2777]).unwrap()); } #[test] fn truncated_lower_hex() { let ar = arr![u8; 10, 20, 30, 40, 50]; assert_eq!(format!("{:.2x}", ar), "0a"); assert_eq!(format!("{:.3x}", ar), "0a1"); assert_eq!(format!("{:.4x}", ar), "0a14"); } #[test] fn truncated_upper_hex() { let ar = arr![u8; 30, 20, 10, 17, 0]; assert_eq!(format!("{:.4X}", ar), "1E14"); assert_eq!(format!("{:.5X}", ar), "1E140"); assert_eq!(format!("{:.6X}", ar), "1E140A"); assert_eq!(format!("{:.7X}", ar), "1E140A1"); assert_eq!(format!("{:.8X}", ar), "1E140A11"); } generic-array-0.12.0/tests/import_name.rs000064400000000000000000000004161326076245500165450ustar0000000000000000#[macro_use] extern crate generic_array as gen_arr; use gen_arr::typenum; #[test] fn test_different_crate_name() { let _: gen_arr::GenericArray = arr![u32; 0, 1, 2, 3]; let _: gen_arr::GenericArray = arr![u32;]; } generic-array-0.12.0/tests/iter.rs000064400000000000000000000101461326076245500151770ustar0000000000000000#[macro_use] extern crate generic_array; use std::cell::Cell; use std::ops::Drop; use generic_array::GenericArray; use generic_array::typenum::consts::U5; #[test] fn test_into_iter_as_slice() { let array = arr![char; 'a', 'b', 'c']; let mut into_iter = array.into_iter(); assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); let _ = into_iter.next().unwrap(); assert_eq!(into_iter.as_slice(), &['b', 'c']); let _ = into_iter.next().unwrap(); let _ = into_iter.next().unwrap(); assert_eq!(into_iter.as_slice(), &[]); } #[test] fn test_into_iter_as_mut_slice() { let array = arr![char; 'a', 'b', 'c']; let mut into_iter = array.into_iter(); assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); into_iter.as_mut_slice()[0] = 'x'; into_iter.as_mut_slice()[1] = 'y'; assert_eq!(into_iter.next().unwrap(), 'x'); assert_eq!(into_iter.as_slice(), &['y', 'c']); } #[test] fn test_into_iter_debug() { let array = arr![char; 'a', 'b', 'c']; let into_iter = array.into_iter(); let debug = format!("{:?}", into_iter); assert_eq!(debug, "GenericArrayIter(['a', 'b', 'c'])"); } #[test] fn test_into_iter_clone() { fn iter_equal>(it: I, slice: &[i32]) { let v: Vec = it.collect(); assert_eq!(&v[..], slice); } let mut it = arr![i32; 1, 2, 3].into_iter(); iter_equal(it.clone(), &[1, 2, 3]); assert_eq!(it.next(), Some(1)); let mut it = it.rev(); iter_equal(it.clone(), &[3, 2]); assert_eq!(it.next(), Some(3)); iter_equal(it.clone(), &[2]); assert_eq!(it.next(), Some(2)); iter_equal(it.clone(), &[]); assert_eq!(it.next(), None); } #[test] fn test_into_iter_nth() { let v = arr![i32; 0, 1, 2, 3, 4]; for i in 0..v.len() { assert_eq!(v.clone().into_iter().nth(i).unwrap(), v[i]); } assert_eq!(v.clone().into_iter().nth(v.len()), None); let mut iter = v.into_iter(); assert_eq!(iter.nth(2).unwrap(), v[2]); assert_eq!(iter.nth(1).unwrap(), v[4]); } #[test] fn test_into_iter_last() { let v = arr![i32; 0, 1, 2, 3, 4]; assert_eq!(v.into_iter().last().unwrap(), 4); assert_eq!(arr![i32; 0].into_iter().last().unwrap(), 0); } #[test] fn test_into_iter_count() { let v = arr![i32; 0, 1, 2, 3, 4]; assert_eq!(v.clone().into_iter().count(), 5); let mut iter2 = v.into_iter(); iter2.next(); iter2.next(); assert_eq!(iter2.count(), 3); } #[test] fn test_into_iter_flat_map() { assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10)); } #[test] fn test_into_iter_drops() { struct R<'a> { i: &'a Cell, } impl<'a> Drop for R<'a> { fn drop(&mut self) { self.i.set(self.i.get() + 1); } } fn r(i: &Cell) -> R { R { i: i } } fn v(i: &Cell) -> GenericArray { arr![R; r(i), r(i), r(i), r(i), r(i)] } let i = Cell::new(0); { v(&i).into_iter(); } assert_eq!(i.get(), 5); let i = Cell::new(0); { let mut iter = v(&i).into_iter(); let _x = iter.next(); assert_eq!(i.get(), 0); assert_eq!(iter.count(), 4); assert_eq!(i.get(), 4); } assert_eq!(i.get(), 5); let i = Cell::new(0); { let mut iter = v(&i).into_iter(); let _x = iter.nth(2); assert_eq!(i.get(), 2); let _y = iter.last(); assert_eq!(i.get(), 3); } assert_eq!(i.get(), 5); let i = Cell::new(0); for (index, _x) in v(&i).into_iter().enumerate() { assert_eq!(i.get(), index); } assert_eq!(i.get(), 5); let i = Cell::new(0); for (index, _x) in v(&i).into_iter().rev().enumerate() { assert_eq!(i.get(), index); } assert_eq!(i.get(), 5); } /* //TODO: Cover this #[allow(dead_code)] fn assert_covariance() { fn into_iter<'new>(i: GenericArrayIter<&'static str, U10>) -> GenericArrayIter<&'new str, U10> { i } } */generic-array-0.12.0/tests/mod.rs000064400000000000000000000150661326076245500150210ustar0000000000000000#![recursion_limit = "128"] #![no_std] #[macro_use] extern crate generic_array; use core::cell::Cell; use core::ops::{Add, Drop}; use generic_array::GenericArray; use generic_array::functional::*; use generic_array::sequence::*; use generic_array::typenum::{U1, U3, U4, U97}; #[test] fn test() { let mut list97 = [0; 97]; for i in 0..97 { list97[i] = i as i32; } let l: GenericArray = GenericArray::clone_from_slice(&list97); assert_eq!(l[0], 0); assert_eq!(l[1], 1); assert_eq!(l[32], 32); assert_eq!(l[56], 56); } #[test] fn test_drop() { #[derive(Clone)] struct TestDrop<'a>(&'a Cell); impl<'a> Drop for TestDrop<'a> { fn drop(&mut self) { self.0.set(self.0.get() + 1); } } let drop_counter = Cell::new(0); { let _: GenericArray = arr![TestDrop; TestDrop(&drop_counter), TestDrop(&drop_counter), TestDrop(&drop_counter)]; } assert_eq!(drop_counter.get(), 3); } #[test] fn test_arr() { let test: GenericArray = arr![u32; 1, 2, 3]; assert_eq!(test[1], 2); } #[test] fn test_copy() { let test = arr![u32; 1, 2, 3]; let test2 = test; // if GenericArray is not copy, this should fail as a use of a moved value assert_eq!(test[1], 2); assert_eq!(test2[0], 1); } #[derive(Debug, PartialEq, Eq)] struct NoClone(T); #[test] fn test_from_slice() { let arr = [1, 2, 3, 4]; let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]); assert_eq!(&arr[..3], gen_arr.as_slice()); let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)]; let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]); assert_eq!(&arr[..3], gen_arr.as_slice()); } #[test] fn test_from_mut_slice() { let mut arr = [1, 2, 3, 4]; { let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]); gen_arr[2] = 10; } assert_eq!(arr, [1, 2, 10, 4]); let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)]; { let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]); gen_arr[2] = NoClone(10); } assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]); } #[test] fn test_default() { let arr = GenericArray::::default(); assert_eq!(arr[0], 0); } #[test] fn test_from() { let data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]; let garray: GenericArray<(usize, usize, usize), U3> = data.into(); assert_eq!(&data, garray.as_slice()); } #[test] fn test_unit_macro() { let arr = arr![f32; 3.14]; assert_eq!(arr[0], 3.14); } #[test] fn test_empty_macro() { let _arr = arr![f32;]; } #[test] fn test_cmp() { arr![u8; 0x00].cmp(&arr![u8; 0x00]); } /// This test should cause a helpful compile error if uncommented. // #[test] // fn test_empty_macro2(){ // let arr = arr![]; // } #[cfg(feature = "serde")] mod impl_serde { extern crate serde_json; use generic_array::GenericArray; use generic_array::typenum::U6; #[test] fn test_serde_implementation() { let array: GenericArray = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0]; let string = serde_json::to_string(&array).unwrap(); assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]"); let test_array: GenericArray = serde_json::from_str(&string).unwrap(); assert_eq!(test_array, array); } } #[test] fn test_map() { let b: GenericArray = GenericArray::generate(|i| i as i32 * 4).map(|x| x - 3); assert_eq!(b, arr![i32; -3, 1, 5, 9]); } #[test] fn test_zip() { let a: GenericArray<_, U4> = GenericArray::generate(|i| i + 1); let b: GenericArray<_, U4> = GenericArray::generate(|i| i as i32 * 4); // Uses reference and non-reference arguments let c = (&a).zip(b, |r, l| *r as i32 + l); assert_eq!(c, arr![i32; 1, 6, 11, 16]); } #[test] #[should_panic] fn test_from_iter_short() { use core::iter::repeat; let a: GenericArray<_, U4> = repeat(11).take(3).collect(); assert_eq!(a, arr![i32; 11, 11, 11, 0]); } #[test] fn test_from_iter() { use core::iter::{once, repeat}; let a: GenericArray<_, U4> = repeat(11).take(3).chain(once(0)).collect(); assert_eq!(a, arr![i32; 11, 11, 11, 0]); } #[test] fn test_sizes() { #![allow(dead_code)] use core::mem::{size_of, size_of_val}; #[derive(Debug, Copy, Clone)] #[repr(C)] #[repr(packed)] struct Test { t: u16, s: u32, r: u16, f: u16, o: u32, } assert_eq!(size_of::(), 14); assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::() * 3); assert_eq!(size_of_val(&arr![u32; 1]), size_of::() * 1); assert_eq!(size_of_val(&arr![u64; 1, 2, 3, 4]), size_of::() * 4); assert_eq!(size_of::>(), size_of::() * 97); } #[test] fn test_append() { let a = arr![i32; 1, 2, 3]; let b = a.append(4); assert_eq!(b, arr![i32; 1, 2, 3, 4]); } #[test] fn test_prepend() { let a = arr![i32; 1, 2, 3]; let b = a.prepend(4); assert_eq!(b, arr![i32; 4, 1, 2, 3]); } #[test] fn test_pop() { let a = arr![i32; 1, 2, 3, 4]; let (init, last) = a.pop_back(); assert_eq!(init, arr![i32; 1, 2, 3]); assert_eq!(last, 4); let (head, tail) = a.pop_front(); assert_eq!(head, 1); assert_eq!(tail, arr![i32; 2, 3, 4]); } #[test] fn test_split() { let a = arr![i32; 1, 2, 3, 4]; let (b, c) = a.split(); assert_eq!(b, arr![i32; 1]); assert_eq!(c, arr![i32; 2, 3, 4]); let (e, f) = a.split(); assert_eq!(e, arr![i32; 1, 2]); assert_eq!(f, arr![i32; 3, 4]); } #[test] fn test_concat() { let a = arr![i32; 1, 2]; let b = arr![i32; 3, 4]; let c = a.concat(b); assert_eq!(c, arr![i32; 1, 2, 3, 4]); let (d, e) = c.split(); assert_eq!(d, arr![i32; 1]); assert_eq!(e, arr![i32; 2, 3, 4]); } #[test] fn test_fold() { let a = arr![i32; 1, 2, 3, 4]; assert_eq!(10, a.fold(0, |a, x| a + x)); } fn sum_generic(s: S) -> i32 where S: FunctionalSequence, S::Item: Add, // `+` i32: Add, // reflexive { s.fold(0, |a, x| a + x) } #[test] fn test_sum() { let a = sum_generic(arr![i32; 1, 2, 3, 4]); assert_eq!(a, 10); }