set gitattributes for rust & cargo so hashes dont conflict on Windows

This commit is contained in:
Grant Limberg
2023-03-01 14:16:51 -08:00
parent dc54e0e1c4
commit 032dc5c108
595 changed files with 74701 additions and 74694 deletions

View File

@@ -1,93 +1,93 @@
* **`0.14.5`**
* Fix unsoundness behavior in `GenericArrayIter::clone` ([#120](https://github.com/fizyk20/generic-array/pull/120))
* **`0.14.4`**
* Update `typenum` to `1.12.0`
* Make `Drop` a no-op when the inner type does not require `Drop` (using `core::mem::needs_drop`)
* **`0.14.3`**
* Improve behavior of `GenericArray::from_exact_iter` to assume `ExactIterator`s can lie.
* Fix alignment of zero-length `GenericArray`s
* Implement `From<&[T; N]> for &GenericArray<T, N>` and its mutable variant
* **`0.14.2`**
* Lower MSRV to `1.36.0` without `From<[T; N]>` implementations.
* **`0.14.1`**
* Fix element conversions in `arr!` macro.
* **`0.14.0`**
* Replace `Into` implementations with the more general `From`.
* Requires minumum Rust version of 1.41.0
* Fix unsoundness in `arr!` macro.
* Fix meta variable misuse
* Fix Undefined Behavior across the crate by switching to `MaybeUninit`
* Improve some documentation and doctests
* Add `AsRef<[T; N]>` and `AsMut<[T; N]>` impls to `GenericArray<T, N>`
* Add `Split` impl for `&GenericArray` and `&mut GenericArray`
* **`0.13.2`**
* Add feature `more_lengths`, which adds more `From`/`Into` implementations for arrays of various lengths.
* **`0.13.1`**
* Mark `GenericArray` as `#[repr(transparent)]`
* Implement `Into<[T; N]>` for `GenericArray<T, N>` up to N=32
* **`0.13.0`**
* Allow `arr!` to be imported with use syntax.
* Requires minumum Rust version of 1.30.1
* **`0.12.2`**
* Implement `FusedIterator` for `GenericArrayIter`
* **`0.12.1`**
* Use internal iteration where possible and provide more efficient internal iteration methods.
* **`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<u8, N>`
* 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
* **`0.14.5`**
* Fix unsoundness behavior in `GenericArrayIter::clone` ([#120](https://github.com/fizyk20/generic-array/pull/120))
* **`0.14.4`**
* Update `typenum` to `1.12.0`
* Make `Drop` a no-op when the inner type does not require `Drop` (using `core::mem::needs_drop`)
* **`0.14.3`**
* Improve behavior of `GenericArray::from_exact_iter` to assume `ExactIterator`s can lie.
* Fix alignment of zero-length `GenericArray`s
* Implement `From<&[T; N]> for &GenericArray<T, N>` and its mutable variant
* **`0.14.2`**
* Lower MSRV to `1.36.0` without `From<[T; N]>` implementations.
* **`0.14.1`**
* Fix element conversions in `arr!` macro.
* **`0.14.0`**
* Replace `Into` implementations with the more general `From`.
* Requires minumum Rust version of 1.41.0
* Fix unsoundness in `arr!` macro.
* Fix meta variable misuse
* Fix Undefined Behavior across the crate by switching to `MaybeUninit`
* Improve some documentation and doctests
* Add `AsRef<[T; N]>` and `AsMut<[T; N]>` impls to `GenericArray<T, N>`
* Add `Split` impl for `&GenericArray` and `&mut GenericArray`
* **`0.13.2`**
* Add feature `more_lengths`, which adds more `From`/`Into` implementations for arrays of various lengths.
* **`0.13.1`**
* Mark `GenericArray` as `#[repr(transparent)]`
* Implement `Into<[T; N]>` for `GenericArray<T, N>` up to N=32
* **`0.13.0`**
* Allow `arr!` to be imported with use syntax.
* Requires minumum Rust version of 1.30.1
* **`0.12.2`**
* Implement `FusedIterator` for `GenericArrayIter`
* **`0.12.1`**
* Use internal iteration where possible and provide more efficient internal iteration methods.
* **`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<u8, N>`
* 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

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,21 @@
The 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
The 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.

View File

@@ -1,62 +1,62 @@
[![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.
**Requires minumum Rust version of 1.36.0, or 1.41.0 for `From<[T; N]>` implementations**
[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<N> {
data: [i32; N]
}
```
**generic-array** defines a new trait `ArrayLength<T>` and a struct `GenericArray<T, N: ArrayLength<T>>`, which let the above be implemented as:
```rust
struct Foo<N: ArrayLength<i32>> {
data: GenericArray<i32, N>
}
```
The `ArrayLength<T>` trait is implemented by default for [unsigned integer types](http://fizyk20.github.io/generic-array/typenum/uint/index.html) from [typenum](http://fizyk20.github.io/generic-array/typenum/index.html) crate:
```rust
use generic_array::typenum::U5;
struct Foo<N: ArrayLength<i32>> {
data: GenericArray<i32, N>
}
fn main() {
let foo = Foo::<U5>{data: GenericArray::default()};
}
```
For example, `GenericArray<T, U5>` would work almost like `[T; 5]`:
```rust
use generic_array::typenum::U5;
struct Foo<T, N: ArrayLength<T>> {
data: GenericArray<T, N>
}
fn main() {
let foo = Foo::<i32, U5>{data: GenericArray::default()};
}
```
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);
```
[![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.
**Requires minumum Rust version of 1.36.0, or 1.41.0 for `From<[T; N]>` implementations**
[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<N> {
data: [i32; N]
}
```
**generic-array** defines a new trait `ArrayLength<T>` and a struct `GenericArray<T, N: ArrayLength<T>>`, which let the above be implemented as:
```rust
struct Foo<N: ArrayLength<i32>> {
data: GenericArray<i32, N>
}
```
The `ArrayLength<T>` trait is implemented by default for [unsigned integer types](http://fizyk20.github.io/generic-array/typenum/uint/index.html) from [typenum](http://fizyk20.github.io/generic-array/typenum/index.html) crate:
```rust
use generic_array::typenum::U5;
struct Foo<N: ArrayLength<i32>> {
data: GenericArray<i32, N>
}
fn main() {
let foo = Foo::<U5>{data: GenericArray::default()};
}
```
For example, `GenericArray<T, U5>` would work almost like `[T; 5]`:
```rust
use generic_array::typenum::U5;
struct Foo<T, N: ArrayLength<T>> {
data: GenericArray<T, N>
}
fn main() {
let foo = Foo::<i32, U5>{data: GenericArray::default()};
}
```
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);
```

View File

@@ -1,5 +1,5 @@
fn main() {
if version_check::is_min_version("1.41.0").unwrap_or(false) {
println!("cargo:rustc-cfg=relaxed_coherence");
}
}
fn main() {
if version_check::is_min_version("1.41.0").unwrap_or(false) {
println!("cargo:rustc-cfg=relaxed_coherence");
}
}

View File

@@ -1,3 +1,3 @@
reorder_imports = true
reorder_imported_names = true
use_try_shorthand = true
reorder_imports = true
reorder_imported_names = true
use_try_shorthand = true

View File

@@ -1,125 +1,125 @@
//! Implementation for `arr!` macro.
use super::ArrayLength;
use core::ops::Add;
use typenum::U1;
/// Helper trait for `arr!` macro
pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
/// Resulting length
type Output: ArrayLength<T>;
}
impl<T, N1, N2> AddLength<T, N2> for N1
where
N1: ArrayLength<T> + Add<N2>,
N2: ArrayLength<T>,
<N1 as Add<N2>>::Output: ArrayLength<T>,
{
type Output = <N1 as Add<N2>>::Output;
}
/// Helper type for `arr!` macro
pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
#[doc(hidden)]
#[macro_export]
macro_rules! arr_impl {
(@replace_expr $e:expr) => { 1 };
($T:ty; $N:ty, [$($x:expr),*], []) => ({
const __ARR_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
#[inline(always)]
fn __do_transmute<T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {
unsafe { $crate::transmute(arr) }
}
let _: [(); <$N as $crate::typenum::Unsigned>::USIZE] = [(); __ARR_LENGTH];
__do_transmute::<$T, $N>([$($x as $T),*])
});
($T:ty; $N:ty, [], [$x1:expr]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
);
($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
);
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
);
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($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),* $(,)*) => (
$crate::arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
);
($($x:expr,)+) => (arr![$($x),+]);
() => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
}
mod doctests_only {
///
/// # With ellision
///
/// Testing that lifetimes aren't transmuted when they're ellided.
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&A; a][0]
/// }
/// }
/// ```
///
/// ```rust
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
/// arr![&A; a][0]
/// }
/// }
/// ```
///
/// # Without ellision
///
/// Testing that lifetimes aren't transmuted when they're specified explicitly.
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&'a A; a][0]
/// }
/// }
/// ```
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&'static A; a][0]
/// }
/// }
/// ```
///
/// ```rust
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
/// arr![&'a A; a][0]
/// }
/// }
/// ```
#[allow(dead_code)]
pub enum DocTests {}
}
//! Implementation for `arr!` macro.
use super::ArrayLength;
use core::ops::Add;
use typenum::U1;
/// Helper trait for `arr!` macro
pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
/// Resulting length
type Output: ArrayLength<T>;
}
impl<T, N1, N2> AddLength<T, N2> for N1
where
N1: ArrayLength<T> + Add<N2>,
N2: ArrayLength<T>,
<N1 as Add<N2>>::Output: ArrayLength<T>,
{
type Output = <N1 as Add<N2>>::Output;
}
/// Helper type for `arr!` macro
pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
#[doc(hidden)]
#[macro_export]
macro_rules! arr_impl {
(@replace_expr $e:expr) => { 1 };
($T:ty; $N:ty, [$($x:expr),*], []) => ({
const __ARR_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
#[inline(always)]
fn __do_transmute<T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {
unsafe { $crate::transmute(arr) }
}
let _: [(); <$N as $crate::typenum::Unsigned>::USIZE] = [(); __ARR_LENGTH];
__do_transmute::<$T, $N>([$($x as $T),*])
});
($T:ty; $N:ty, [], [$x1:expr]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
);
($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
);
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
);
($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
$crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($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),* $(,)*) => (
$crate::arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
);
($($x:expr,)+) => (arr![$($x),+]);
() => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
}
mod doctests_only {
///
/// # With ellision
///
/// Testing that lifetimes aren't transmuted when they're ellided.
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&A; a][0]
/// }
/// }
/// ```
///
/// ```rust
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
/// arr![&A; a][0]
/// }
/// }
/// ```
///
/// # Without ellision
///
/// Testing that lifetimes aren't transmuted when they're specified explicitly.
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&'a A; a][0]
/// }
/// }
/// ```
///
/// ```compile_fail
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
/// arr![&'static A; a][0]
/// }
/// }
/// ```
///
/// ```rust
/// #[macro_use] extern crate generic_array;
/// fn main() {
/// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
/// arr![&'a A; a][0]
/// }
/// }
/// ```
#[allow(dead_code)]
pub enum DocTests {}
}

View File

@@ -1,95 +1,95 @@
//! 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 crate::sequence::*;
/// Defines the relationship between one generic sequence and another,
/// for operations such as `map` and `zip`.
pub unsafe trait MappedGenericSequence<T, U>: GenericSequence<T>
where
Self::Length: ArrayLength<U>,
{
/// Mapped sequence type
type Mapped: GenericSequence<U, Length = Self::Length>;
}
unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a S
where
&'a S: GenericSequence<T>,
S: GenericSequence<T, Length = <&'a S as GenericSequence<T>>::Length>,
<S as GenericSequence<T>>::Length: ArrayLength<U>,
{
type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
}
unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a mut S
where
&'a mut S: GenericSequence<T>,
S: GenericSequence<T, Length = <&'a mut S as GenericSequence<T>>::Length>,
<S as GenericSequence<T>>::Length: ArrayLength<U>,
{
type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
}
/// Accessor type for a mapped generic sequence
pub type MappedSequence<S, T, U> =
<<S as MappedGenericSequence<T, U>>::Mapped as GenericSequence<U>>::Sequence;
/// Defines functional programming methods for generic sequences
pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {
/// 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<U, F>(self, f: F) -> MappedSequence<Self, T, U>
where
Self: MappedGenericSequence<T, U>,
Self::Length: ArrayLength<U>,
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<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
where
Self: MappedGenericSequence<T, U>,
Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
Self::Length: ArrayLength<B> + ArrayLength<U>,
Rhs: GenericSequence<B, Length = Self::Length>,
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<U, F>(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<T>> FunctionalSequence<T> for &'a S
where
&'a S: GenericSequence<T>,
{
}
unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a mut S
where
&'a mut S: GenericSequence<T>,
{
}
//! 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 crate::sequence::*;
/// Defines the relationship between one generic sequence and another,
/// for operations such as `map` and `zip`.
pub unsafe trait MappedGenericSequence<T, U>: GenericSequence<T>
where
Self::Length: ArrayLength<U>,
{
/// Mapped sequence type
type Mapped: GenericSequence<U, Length = Self::Length>;
}
unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a S
where
&'a S: GenericSequence<T>,
S: GenericSequence<T, Length = <&'a S as GenericSequence<T>>::Length>,
<S as GenericSequence<T>>::Length: ArrayLength<U>,
{
type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
}
unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a mut S
where
&'a mut S: GenericSequence<T>,
S: GenericSequence<T, Length = <&'a mut S as GenericSequence<T>>::Length>,
<S as GenericSequence<T>>::Length: ArrayLength<U>,
{
type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
}
/// Accessor type for a mapped generic sequence
pub type MappedSequence<S, T, U> =
<<S as MappedGenericSequence<T, U>>::Mapped as GenericSequence<U>>::Sequence;
/// Defines functional programming methods for generic sequences
pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {
/// 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<U, F>(self, f: F) -> MappedSequence<Self, T, U>
where
Self: MappedGenericSequence<T, U>,
Self::Length: ArrayLength<U>,
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<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
where
Self: MappedGenericSequence<T, U>,
Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
Self::Length: ArrayLength<B> + ArrayLength<U>,
Rhs: GenericSequence<B, Length = Self::Length>,
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<U, F>(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<T>> FunctionalSequence<T> for &'a S
where
&'a S: GenericSequence<T>,
{
}
unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a mut S
where
&'a mut S: GenericSequence<T>,
{
}

View File

@@ -1,105 +1,105 @@
//! 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 core::{fmt, str, ops::Add, cmp::min};
use typenum::*;
use crate::{ArrayLength, GenericArray};
static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";
impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
where
T: Add<T>,
<T as Add<T>>::Output: ArrayLength<u8>,
{
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::USIZE < 1024 {
// For small arrays use a stack allocated
// buffer of 2x number of bytes
let mut res = GenericArray::<u8, Sum<T, T>>::default();
self.iter().take(max_hex).enumerate().for_each(|(i, c)| {
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) {
chunk.iter().enumerate().for_each(|(i, c)| {
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<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
where
T: Add<T>,
<T as Add<T>>::Output: ArrayLength<u8>,
{
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::USIZE < 1024 {
// For small arrays use a stack allocated
// buffer of 2x number of bytes
let mut res = GenericArray::<u8, Sum<T, T>>::default();
self.iter().take(max_hex).enumerate().for_each(|(i, c)| {
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) {
chunk.iter().enumerate().for_each(|(i, c)| {
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 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 core::{fmt, str, ops::Add, cmp::min};
use typenum::*;
use crate::{ArrayLength, GenericArray};
static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";
impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
where
T: Add<T>,
<T as Add<T>>::Output: ArrayLength<u8>,
{
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::USIZE < 1024 {
// For small arrays use a stack allocated
// buffer of 2x number of bytes
let mut res = GenericArray::<u8, Sum<T, T>>::default();
self.iter().take(max_hex).enumerate().for_each(|(i, c)| {
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) {
chunk.iter().enumerate().for_each(|(i, c)| {
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<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
where
T: Add<T>,
<T as Add<T>>::Output: ArrayLength<u8>,
{
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::USIZE < 1024 {
// For small arrays use a stack allocated
// buffer of 2x number of bytes
let mut res = GenericArray::<u8, Sum<T, T>>::default();
self.iter().take(max_hex).enumerate().for_each(|(i, c)| {
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) {
chunk.iter().enumerate().for_each(|(i, c)| {
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(())
}
}

View File

@@ -1,108 +1,108 @@
//! 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<T, N> Serialize for GenericArray<T, N>
where
T: Serialize,
N: ArrayLength<T>,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut tup = serializer.serialize_tuple(N::USIZE)?;
for el in self {
tup.serialize_element(el)?;
}
tup.end()
}
}
struct GAVisitor<T, N> {
_t: PhantomData<T>,
_n: PhantomData<N>,
}
impl<'de, T, N> Visitor<'de> for GAVisitor<T, N>
where
T: Deserialize<'de> + Default,
N: ArrayLength<T>,
{
type Value = GenericArray<T, N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct GenericArray")
}
fn visit_seq<A>(self, mut seq: A) -> Result<GenericArray<T, N>, A::Error>
where
A: SeqAccess<'de>,
{
let mut result = GenericArray::default();
for i in 0..N::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<T, N>
where
T: Deserialize<'de> + Default,
N: ArrayLength<T>,
{
fn deserialize<D>(deserializer: D) -> Result<GenericArray<T, N>, D::Error>
where
D: Deserializer<'de>,
{
let visitor = GAVisitor {
_t: PhantomData,
_n: PhantomData,
};
deserializer.deserialize_tuple(N::USIZE, visitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
use bincode;
use typenum;
#[test]
fn test_serialize() {
let array = GenericArray::<u8, typenum::U2>::default();
let serialized = bincode::serialize(&array);
assert!(serialized.is_ok());
}
#[test]
fn test_deserialize() {
let mut array = GenericArray::<u8, typenum::U2>::default();
array[0] = 1;
array[1] = 2;
let serialized = bincode::serialize(&array).unwrap();
let deserialized = bincode::deserialize::<GenericArray<u8, typenum::U2>>(&serialized);
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::<u8, typenum::U1>::default();
let size = bincode::serialized_size(&array).unwrap();
assert_eq!(size, 1);
}
}
//! 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<T, N> Serialize for GenericArray<T, N>
where
T: Serialize,
N: ArrayLength<T>,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut tup = serializer.serialize_tuple(N::USIZE)?;
for el in self {
tup.serialize_element(el)?;
}
tup.end()
}
}
struct GAVisitor<T, N> {
_t: PhantomData<T>,
_n: PhantomData<N>,
}
impl<'de, T, N> Visitor<'de> for GAVisitor<T, N>
where
T: Deserialize<'de> + Default,
N: ArrayLength<T>,
{
type Value = GenericArray<T, N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct GenericArray")
}
fn visit_seq<A>(self, mut seq: A) -> Result<GenericArray<T, N>, A::Error>
where
A: SeqAccess<'de>,
{
let mut result = GenericArray::default();
for i in 0..N::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<T, N>
where
T: Deserialize<'de> + Default,
N: ArrayLength<T>,
{
fn deserialize<D>(deserializer: D) -> Result<GenericArray<T, N>, D::Error>
where
D: Deserializer<'de>,
{
let visitor = GAVisitor {
_t: PhantomData,
_n: PhantomData,
};
deserializer.deserialize_tuple(N::USIZE, visitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
use bincode;
use typenum;
#[test]
fn test_serialize() {
let array = GenericArray::<u8, typenum::U2>::default();
let serialized = bincode::serialize(&array);
assert!(serialized.is_ok());
}
#[test]
fn test_deserialize() {
let mut array = GenericArray::<u8, typenum::U2>::default();
array[0] = 1;
array[1] = 2;
let serialized = bincode::serialize(&array).unwrap();
let deserialized = bincode::deserialize::<GenericArray<u8, typenum::U2>>(&serialized);
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::<u8, typenum::U1>::default();
let size = bincode::serialized_size(&array).unwrap();
assert_eq!(size, 1);
}
}

View File

@@ -1,269 +1,269 @@
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use super::{ArrayLength, GenericArray};
use crate::functional::*;
use crate::sequence::*;
impl<T: Default, N> Default for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn default() -> Self {
Self::generate(|_| T::default())
}
}
impl<T: Clone, N> Clone for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn clone(&self) -> GenericArray<T, N> {
self.map(Clone::clone)
}
}
impl<T: Copy, N> Copy for GenericArray<T, N>
where
N: ArrayLength<T>,
N::ArrayType: Copy,
{
}
impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}
impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
}
}
impl<T: Ord, N> Ord for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
Ord::cmp(self.as_slice(), other.as_slice())
}
}
impl<T: Debug, N> Debug for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self[..].fmt(fmt)
}
}
impl<T, N> Borrow<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn borrow(&self) -> &[T] {
&self[..]
}
}
impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn borrow_mut(&mut self) -> &mut [T] {
&mut self[..]
}
}
impl<T, N> AsRef<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn as_ref(&self) -> &[T] {
&self[..]
}
}
impl<T, N> AsMut<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn as_mut(&mut self) -> &mut [T] {
&mut self[..]
}
}
impl<T: Hash, N> Hash for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
Hash::hash(&self[..], state)
}
}
macro_rules! impl_from {
($($n: expr => $ty: ty),*) => {
$(
impl<T> From<[T; $n]> for GenericArray<T, $ty> {
#[inline(always)]
fn from(arr: [T; $n]) -> Self {
unsafe { $crate::transmute(arr) }
}
}
#[cfg(relaxed_coherence)]
impl<T> From<GenericArray<T, $ty>> for [T; $n] {
#[inline(always)]
fn from(sel: GenericArray<T, $ty>) -> [T; $n] {
unsafe { $crate::transmute(sel) }
}
}
impl<'a, T> From<&'a [T; $n]> for &'a GenericArray<T, $ty> {
#[inline]
fn from(slice: &[T; $n]) -> &GenericArray<T, $ty> {
unsafe { &*(slice.as_ptr() as *const GenericArray<T, $ty>) }
}
}
impl<'a, T> From<&'a mut [T; $n]> for &'a mut GenericArray<T, $ty> {
#[inline]
fn from(slice: &mut [T; $n]) -> &mut GenericArray<T, $ty> {
unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, $ty>) }
}
}
#[cfg(not(relaxed_coherence))]
impl<T> Into<[T; $n]> for GenericArray<T, $ty> {
#[inline(always)]
fn into(self) -> [T; $n] {
unsafe { $crate::transmute(self) }
}
}
impl<T> AsRef<[T; $n]> for GenericArray<T, $ty> {
#[inline]
fn as_ref(&self) -> &[T; $n] {
unsafe { $crate::transmute(self) }
}
}
impl<T> AsMut<[T; $n]> for GenericArray<T, $ty> {
#[inline]
fn as_mut(&mut self) -> &mut [T; $n] {
unsafe { $crate::transmute(self) }
}
}
)*
}
}
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
}
#[cfg(feature = "more_lengths")]
impl_from! {
33 => ::typenum::U33,
34 => ::typenum::U34,
35 => ::typenum::U35,
36 => ::typenum::U36,
37 => ::typenum::U37,
38 => ::typenum::U38,
39 => ::typenum::U39,
40 => ::typenum::U40,
41 => ::typenum::U41,
42 => ::typenum::U42,
43 => ::typenum::U43,
44 => ::typenum::U44,
45 => ::typenum::U45,
46 => ::typenum::U46,
47 => ::typenum::U47,
48 => ::typenum::U48,
49 => ::typenum::U49,
50 => ::typenum::U50,
51 => ::typenum::U51,
52 => ::typenum::U52,
53 => ::typenum::U53,
54 => ::typenum::U54,
55 => ::typenum::U55,
56 => ::typenum::U56,
57 => ::typenum::U57,
58 => ::typenum::U58,
59 => ::typenum::U59,
60 => ::typenum::U60,
61 => ::typenum::U61,
62 => ::typenum::U62,
63 => ::typenum::U63,
64 => ::typenum::U64,
70 => ::typenum::U70,
80 => ::typenum::U80,
90 => ::typenum::U90,
100 => ::typenum::U100,
200 => ::typenum::U200,
300 => ::typenum::U300,
400 => ::typenum::U400,
500 => ::typenum::U500,
128 => ::typenum::U128,
256 => ::typenum::U256,
512 => ::typenum::U512,
1000 => ::typenum::U1000,
1024 => ::typenum::U1024
}
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use super::{ArrayLength, GenericArray};
use crate::functional::*;
use crate::sequence::*;
impl<T: Default, N> Default for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn default() -> Self {
Self::generate(|_| T::default())
}
}
impl<T: Clone, N> Clone for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn clone(&self) -> GenericArray<T, N> {
self.map(Clone::clone)
}
}
impl<T: Copy, N> Copy for GenericArray<T, N>
where
N: ArrayLength<T>,
N::ArrayType: Copy,
{
}
impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn eq(&self, other: &Self) -> bool {
**self == **other
}
}
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}
impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
}
}
impl<T: Ord, N> Ord for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
Ord::cmp(self.as_slice(), other.as_slice())
}
}
impl<T: Debug, N> Debug for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self[..].fmt(fmt)
}
}
impl<T, N> Borrow<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn borrow(&self) -> &[T] {
&self[..]
}
}
impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn borrow_mut(&mut self) -> &mut [T] {
&mut self[..]
}
}
impl<T, N> AsRef<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn as_ref(&self) -> &[T] {
&self[..]
}
}
impl<T, N> AsMut<[T]> for GenericArray<T, N>
where
N: ArrayLength<T>,
{
#[inline(always)]
fn as_mut(&mut self) -> &mut [T] {
&mut self[..]
}
}
impl<T: Hash, N> Hash for GenericArray<T, N>
where
N: ArrayLength<T>,
{
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
Hash::hash(&self[..], state)
}
}
macro_rules! impl_from {
($($n: expr => $ty: ty),*) => {
$(
impl<T> From<[T; $n]> for GenericArray<T, $ty> {
#[inline(always)]
fn from(arr: [T; $n]) -> Self {
unsafe { $crate::transmute(arr) }
}
}
#[cfg(relaxed_coherence)]
impl<T> From<GenericArray<T, $ty>> for [T; $n] {
#[inline(always)]
fn from(sel: GenericArray<T, $ty>) -> [T; $n] {
unsafe { $crate::transmute(sel) }
}
}
impl<'a, T> From<&'a [T; $n]> for &'a GenericArray<T, $ty> {
#[inline]
fn from(slice: &[T; $n]) -> &GenericArray<T, $ty> {
unsafe { &*(slice.as_ptr() as *const GenericArray<T, $ty>) }
}
}
impl<'a, T> From<&'a mut [T; $n]> for &'a mut GenericArray<T, $ty> {
#[inline]
fn from(slice: &mut [T; $n]) -> &mut GenericArray<T, $ty> {
unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, $ty>) }
}
}
#[cfg(not(relaxed_coherence))]
impl<T> Into<[T; $n]> for GenericArray<T, $ty> {
#[inline(always)]
fn into(self) -> [T; $n] {
unsafe { $crate::transmute(self) }
}
}
impl<T> AsRef<[T; $n]> for GenericArray<T, $ty> {
#[inline]
fn as_ref(&self) -> &[T; $n] {
unsafe { $crate::transmute(self) }
}
}
impl<T> AsMut<[T; $n]> for GenericArray<T, $ty> {
#[inline]
fn as_mut(&mut self) -> &mut [T; $n] {
unsafe { $crate::transmute(self) }
}
}
)*
}
}
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
}
#[cfg(feature = "more_lengths")]
impl_from! {
33 => ::typenum::U33,
34 => ::typenum::U34,
35 => ::typenum::U35,
36 => ::typenum::U36,
37 => ::typenum::U37,
38 => ::typenum::U38,
39 => ::typenum::U39,
40 => ::typenum::U40,
41 => ::typenum::U41,
42 => ::typenum::U42,
43 => ::typenum::U43,
44 => ::typenum::U44,
45 => ::typenum::U45,
46 => ::typenum::U46,
47 => ::typenum::U47,
48 => ::typenum::U48,
49 => ::typenum::U49,
50 => ::typenum::U50,
51 => ::typenum::U51,
52 => ::typenum::U52,
53 => ::typenum::U53,
54 => ::typenum::U54,
55 => ::typenum::U55,
56 => ::typenum::U56,
57 => ::typenum::U57,
58 => ::typenum::U58,
59 => ::typenum::U59,
60 => ::typenum::U60,
61 => ::typenum::U61,
62 => ::typenum::U62,
63 => ::typenum::U63,
64 => ::typenum::U64,
70 => ::typenum::U70,
80 => ::typenum::U80,
90 => ::typenum::U90,
100 => ::typenum::U100,
200 => ::typenum::U200,
300 => ::typenum::U300,
400 => ::typenum::U400,
500 => ::typenum::U500,
128 => ::typenum::U128,
256 => ::typenum::U256,
512 => ::typenum::U512,
1000 => ::typenum::U1000,
1024 => ::typenum::U1024
}

View File

@@ -1,256 +1,256 @@
//! `GenericArray` iterator implementation.
use super::{ArrayLength, GenericArray};
use core::iter::FusedIterator;
use core::mem::ManuallyDrop;
use core::{cmp, fmt, ptr, mem};
/// An iterator that moves out of a `GenericArray`
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
// 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<GenericArray<T, N>>,
index: usize,
index_back: usize,
}
#[cfg(test)]
mod test {
use super::*;
fn send<I: Send>(_iter: I) {}
#[test]
fn test_send_iter() {
send(GenericArray::from([1, 2, 3, 4]).into_iter());
}
}
impl<T, N> GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
/// 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<T, N> IntoIterator for GenericArray<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
type IntoIter = GenericArrayIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
GenericArrayIter {
array: ManuallyDrop::new(self),
index: 0,
index_back: N::USIZE,
}
}
}
// Based on work in rust-lang/rust#49000
impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("GenericArrayIter")
.field(&self.as_slice())
.finish()
}
}
impl<T, N> Drop for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
#[inline]
fn drop(&mut self) {
if mem::needs_drop::<T>() {
// 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<T: Clone, N> Clone for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
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 array = ptr::read(&self.array);
let mut index_back = 0;
for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {
ptr::write(dst, src.clone());
index_back += 1;
}
GenericArrayIter {
array,
index: 0,
index_back
}
}
}
}
impl<T, N> Iterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.index < self.index_back {
let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };
self.index += 1;
p
} else {
None
}
}
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let ret = unsafe {
let GenericArrayIter {
ref array,
ref mut index,
index_back,
} = self;
let remaining = &array[*index..index_back];
remaining.iter().fold(init, |acc, src| {
let value = ptr::read(src);
*index += 1;
f(acc, value)
})
};
// ensure the drop happens here after iteration
drop(self);
ret
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
fn nth(&mut self, n: usize) -> Option<T> {
// 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()
}
#[inline]
fn last(mut self) -> Option<T> {
// Note, everything else will correctly drop first as `self` leaves scope.
self.next_back()
}
}
impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
fn next_back(&mut self) -> Option<T> {
if self.index < self.index_back {
self.index_back -= 1;
unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
} else {
None
}
}
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let ret = unsafe {
let GenericArrayIter {
ref array,
index,
ref mut index_back,
} = self;
let remaining = &array[index..*index_back];
remaining.iter().rfold(init, |acc, src| {
let value = ptr::read(src);
*index_back -= 1;
f(acc, value)
})
};
// ensure the drop happens here after iteration
drop(self);
ret
}
}
impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
fn len(&self) -> usize {
self.index_back - self.index
}
}
impl<T, N> FusedIterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
}
// TODO: Implement `TrustedLen` when stabilized
//! `GenericArray` iterator implementation.
use super::{ArrayLength, GenericArray};
use core::iter::FusedIterator;
use core::mem::ManuallyDrop;
use core::{cmp, fmt, ptr, mem};
/// An iterator that moves out of a `GenericArray`
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
// 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<GenericArray<T, N>>,
index: usize,
index_back: usize,
}
#[cfg(test)]
mod test {
use super::*;
fn send<I: Send>(_iter: I) {}
#[test]
fn test_send_iter() {
send(GenericArray::from([1, 2, 3, 4]).into_iter());
}
}
impl<T, N> GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
/// 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<T, N> IntoIterator for GenericArray<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
type IntoIter = GenericArrayIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
GenericArrayIter {
array: ManuallyDrop::new(self),
index: 0,
index_back: N::USIZE,
}
}
}
// Based on work in rust-lang/rust#49000
impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("GenericArrayIter")
.field(&self.as_slice())
.finish()
}
}
impl<T, N> Drop for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
#[inline]
fn drop(&mut self) {
if mem::needs_drop::<T>() {
// 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<T: Clone, N> Clone for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
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 array = ptr::read(&self.array);
let mut index_back = 0;
for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {
ptr::write(dst, src.clone());
index_back += 1;
}
GenericArrayIter {
array,
index: 0,
index_back
}
}
}
}
impl<T, N> Iterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.index < self.index_back {
let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };
self.index += 1;
p
} else {
None
}
}
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let ret = unsafe {
let GenericArrayIter {
ref array,
ref mut index,
index_back,
} = self;
let remaining = &array[*index..index_back];
remaining.iter().fold(init, |acc, src| {
let value = ptr::read(src);
*index += 1;
f(acc, value)
})
};
// ensure the drop happens here after iteration
drop(self);
ret
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline]
fn count(self) -> usize {
self.len()
}
fn nth(&mut self, n: usize) -> Option<T> {
// 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()
}
#[inline]
fn last(mut self) -> Option<T> {
// Note, everything else will correctly drop first as `self` leaves scope.
self.next_back()
}
}
impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
fn next_back(&mut self) -> Option<T> {
if self.index < self.index_back {
self.index_back -= 1;
unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
} else {
None
}
}
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
let ret = unsafe {
let GenericArrayIter {
ref array,
index,
ref mut index_back,
} = self;
let remaining = &array[index..*index_back];
remaining.iter().rfold(init, |acc, src| {
let value = ptr::read(src);
*index_back -= 1;
f(acc, value)
})
};
// ensure the drop happens here after iteration
drop(self);
ret
}
}
impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
fn len(&self) -> usize {
self.index_back - self.index
}
}
impl<T, N> FusedIterator for GenericArrayIter<T, N>
where
N: ArrayLength<T>,
{
}
// TODO: Implement `TrustedLen` when stabilized

File diff suppressed because it is too large Load Diff

View File

@@ -1,380 +1,380 @@
//! Useful traits for manipulating sequences of data stored in `GenericArray`s
use super::*;
use core::ops::{Add, Sub};
use core::mem::MaybeUninit;
use core::ptr;
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<T>: Sized + IntoIterator {
/// `GenericArray` associated length
type Length: ArrayLength<T>;
/// Concrete sequence type used in conjuction with reference implementations of `GenericSequence`
type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;
/// 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: F) -> Self::Sequence
where
F: FnMut(usize) -> T;
#[doc(hidden)]
fn inverted_zip<B, U, F>(
self,
lhs: GenericArray<B, Self::Length>,
mut f: F,
) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
where
GenericArray<B, Self::Length>: GenericSequence<B, Length = Self::Length>
+ MappedGenericSequence<B, U>,
Self: MappedGenericSequence<T, U>,
Self::Length: ArrayLength<B> + ArrayLength<U>,
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<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
where
Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
Self: MappedGenericSequence<T, U>,
Self::Length: ArrayLength<B> + ArrayLength<U>,
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<T> = <T as IntoIterator>::Item;
unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S
where
&'a S: IntoIterator,
{
type Length = S::Length;
type Sequence = S::Sequence;
#[inline]
fn generate<F>(f: F) -> Self::Sequence
where
F: FnMut(usize) -> T,
{
S::generate(f)
}
}
unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S
where
&'a mut S: IntoIterator,
{
type Length = S::Length;
type Sequence = S::Sequence;
#[inline]
fn generate<F>(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<T>: Sized + GenericSequence<T> {
/// `GenericSequence` that has one more element than `Self`
type Longer: Shorten<T, Shorter = Self>;
/// Returns a new array with the given element appended to the end of it.
///
/// Example:
///
/// ```rust
/// # use generic_array::{arr, sequence::Lengthen};
/// # fn main() {
/// 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:
///
/// ```rust
/// # use generic_array::{arr, sequence::Lengthen};
/// # fn main() {
/// 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<T>: Sized + GenericSequence<T> {
/// `GenericSequence` that has one less element than `Self`
type Shorter: Lengthen<T, Longer = Self>;
/// Returns a new array without the last element, and the last element.
///
/// Example:
///
/// ```rust
/// # use generic_array::{arr, sequence::Shorten};
/// # fn main() {
/// 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:
///
/// ```rust
/// # use generic_array::{arr, sequence::Shorten};
/// # fn main() {
/// 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<T, N: ArrayLength<T>> Lengthen<T> for GenericArray<T, N>
where
N: Add<B1>,
Add1<N>: ArrayLength<T>,
Add1<N>: Sub<B1, Output = N>,
Sub1<Add1<N>>: ArrayLength<T>,
{
type Longer = GenericArray<T, Add1<N>>;
fn append(self, last: T) -> Self::Longer {
let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
// Note this is *mut Self, so add(1) increments by the whole array
let out_ptr = longer.as_mut_ptr() as *mut Self;
unsafe {
// write self first
ptr::write(out_ptr, self);
// increment past self, then write the last
ptr::write(out_ptr.add(1) as *mut T, last);
longer.assume_init()
}
}
fn prepend(self, first: T) -> Self::Longer {
let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
// Note this is *mut T, so add(1) increments by a single T
let out_ptr = longer.as_mut_ptr() as *mut T;
unsafe {
// write the first at the start
ptr::write(out_ptr, first);
// increment past the first, then write self
ptr::write(out_ptr.add(1) as *mut Self, self);
longer.assume_init()
}
}
}
unsafe impl<T, N: ArrayLength<T>> Shorten<T> for GenericArray<T, N>
where
N: Sub<B1>,
Sub1<N>: ArrayLength<T>,
Sub1<N>: Add<B1, Output = N>,
Add1<Sub1<N>>: ArrayLength<T>,
{
type Shorter = GenericArray<T, Sub1<N>>;
fn pop_back(self) -> (Self::Shorter, T) {
let whole = ManuallyDrop::new(self);
unsafe {
let init = ptr::read(whole.as_ptr() as _);
let last = ptr::read(whole.as_ptr().add(Sub1::<N>::USIZE) as _);
(init, last)
}
}
fn pop_front(self) -> (T, Self::Shorter) {
// ensure this doesn't get dropped
let whole = ManuallyDrop::new(self);
unsafe {
let head = ptr::read(whole.as_ptr() as _);
let tail = ptr::read(whole.as_ptr().offset(1) as _);
(head, tail)
}
}
}
/// Defines a `GenericSequence` that can be split into two parts at a given pivot index.
pub unsafe trait Split<T, K>: GenericSequence<T>
where
K: ArrayLength<T>,
{
/// First part of the resulting split array
type First: GenericSequence<T>;
/// Second part of the resulting split array
type Second: GenericSequence<T>;
/// Splits an array at the given index, returning the separate parts of the array.
fn split(self) -> (Self::First, Self::Second);
}
unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>
where
N: ArrayLength<T>,
K: ArrayLength<T>,
N: Sub<K>,
Diff<N, K>: ArrayLength<T>,
{
type First = GenericArray<T, K>;
type Second = GenericArray<T, Diff<N, K>>;
fn split(self) -> (Self::First, Self::Second) {
unsafe {
// ensure this doesn't get dropped
let whole = ManuallyDrop::new(self);
let head = ptr::read(whole.as_ptr() as *const _);
let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _);
(head, tail)
}
}
}
unsafe impl<'a, T, N, K> Split<T, K> for &'a GenericArray<T, N>
where
N: ArrayLength<T>,
K: ArrayLength<T> + 'static,
N: Sub<K>,
Diff<N, K>: ArrayLength<T>,
{
type First = &'a GenericArray<T, K>;
type Second = &'a GenericArray<T, Diff<N, K>>;
fn split(self) -> (Self::First, Self::Second) {
unsafe {
let ptr_to_first: *const T = self.as_ptr();
let head = &*(ptr_to_first as *const _);
let tail = &*(ptr_to_first.add(K::USIZE) as *const _);
(head, tail)
}
}
}
unsafe impl<'a, T, N, K> Split<T, K> for &'a mut GenericArray<T, N>
where
N: ArrayLength<T>,
K: ArrayLength<T> + 'static,
N: Sub<K>,
Diff<N, K>: ArrayLength<T>,
{
type First = &'a mut GenericArray<T, K>;
type Second = &'a mut GenericArray<T, Diff<N, K>>;
fn split(self) -> (Self::First, Self::Second) {
unsafe {
let ptr_to_first: *mut T = self.as_mut_ptr();
let head = &mut *(ptr_to_first as *mut _);
let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _);
(head, tail)
}
}
}
/// Defines `GenericSequence`s which can be joined together, forming a larger array.
pub unsafe trait Concat<T, M>: GenericSequence<T>
where
M: ArrayLength<T>,
{
/// Sequence to be concatenated with `self`
type Rest: GenericSequence<T, Length = M>;
/// Resulting sequence formed by the concatenation.
type Output: GenericSequence<T>;
/// Concatenate, or join, two sequences.
fn concat(self, rest: Self::Rest) -> Self::Output;
}
unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>
where
N: ArrayLength<T> + Add<M>,
M: ArrayLength<T>,
Sum<N, M>: ArrayLength<T>,
{
type Rest = GenericArray<T, M>;
type Output = GenericArray<T, Sum<N, M>>;
fn concat(self, rest: Self::Rest) -> Self::Output {
let mut output: MaybeUninit<Self::Output> = MaybeUninit::uninit();
let out_ptr = output.as_mut_ptr() as *mut Self;
unsafe {
// write all of self to the pointer
ptr::write(out_ptr, self);
// increment past self, then write the rest
ptr::write(out_ptr.add(1) as *mut _, rest);
output.assume_init()
}
}
}
//! Useful traits for manipulating sequences of data stored in `GenericArray`s
use super::*;
use core::ops::{Add, Sub};
use core::mem::MaybeUninit;
use core::ptr;
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<T>: Sized + IntoIterator {
/// `GenericArray` associated length
type Length: ArrayLength<T>;
/// Concrete sequence type used in conjuction with reference implementations of `GenericSequence`
type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;
/// 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: F) -> Self::Sequence
where
F: FnMut(usize) -> T;
#[doc(hidden)]
fn inverted_zip<B, U, F>(
self,
lhs: GenericArray<B, Self::Length>,
mut f: F,
) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
where
GenericArray<B, Self::Length>: GenericSequence<B, Length = Self::Length>
+ MappedGenericSequence<B, U>,
Self: MappedGenericSequence<T, U>,
Self::Length: ArrayLength<B> + ArrayLength<U>,
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<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
where
Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
Self: MappedGenericSequence<T, U>,
Self::Length: ArrayLength<B> + ArrayLength<U>,
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<T> = <T as IntoIterator>::Item;
unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S
where
&'a S: IntoIterator,
{
type Length = S::Length;
type Sequence = S::Sequence;
#[inline]
fn generate<F>(f: F) -> Self::Sequence
where
F: FnMut(usize) -> T,
{
S::generate(f)
}
}
unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S
where
&'a mut S: IntoIterator,
{
type Length = S::Length;
type Sequence = S::Sequence;
#[inline]
fn generate<F>(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<T>: Sized + GenericSequence<T> {
/// `GenericSequence` that has one more element than `Self`
type Longer: Shorten<T, Shorter = Self>;
/// Returns a new array with the given element appended to the end of it.
///
/// Example:
///
/// ```rust
/// # use generic_array::{arr, sequence::Lengthen};
/// # fn main() {
/// 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:
///
/// ```rust
/// # use generic_array::{arr, sequence::Lengthen};
/// # fn main() {
/// 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<T>: Sized + GenericSequence<T> {
/// `GenericSequence` that has one less element than `Self`
type Shorter: Lengthen<T, Longer = Self>;
/// Returns a new array without the last element, and the last element.
///
/// Example:
///
/// ```rust
/// # use generic_array::{arr, sequence::Shorten};
/// # fn main() {
/// 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:
///
/// ```rust
/// # use generic_array::{arr, sequence::Shorten};
/// # fn main() {
/// 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<T, N: ArrayLength<T>> Lengthen<T> for GenericArray<T, N>
where
N: Add<B1>,
Add1<N>: ArrayLength<T>,
Add1<N>: Sub<B1, Output = N>,
Sub1<Add1<N>>: ArrayLength<T>,
{
type Longer = GenericArray<T, Add1<N>>;
fn append(self, last: T) -> Self::Longer {
let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
// Note this is *mut Self, so add(1) increments by the whole array
let out_ptr = longer.as_mut_ptr() as *mut Self;
unsafe {
// write self first
ptr::write(out_ptr, self);
// increment past self, then write the last
ptr::write(out_ptr.add(1) as *mut T, last);
longer.assume_init()
}
}
fn prepend(self, first: T) -> Self::Longer {
let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();
// Note this is *mut T, so add(1) increments by a single T
let out_ptr = longer.as_mut_ptr() as *mut T;
unsafe {
// write the first at the start
ptr::write(out_ptr, first);
// increment past the first, then write self
ptr::write(out_ptr.add(1) as *mut Self, self);
longer.assume_init()
}
}
}
unsafe impl<T, N: ArrayLength<T>> Shorten<T> for GenericArray<T, N>
where
N: Sub<B1>,
Sub1<N>: ArrayLength<T>,
Sub1<N>: Add<B1, Output = N>,
Add1<Sub1<N>>: ArrayLength<T>,
{
type Shorter = GenericArray<T, Sub1<N>>;
fn pop_back(self) -> (Self::Shorter, T) {
let whole = ManuallyDrop::new(self);
unsafe {
let init = ptr::read(whole.as_ptr() as _);
let last = ptr::read(whole.as_ptr().add(Sub1::<N>::USIZE) as _);
(init, last)
}
}
fn pop_front(self) -> (T, Self::Shorter) {
// ensure this doesn't get dropped
let whole = ManuallyDrop::new(self);
unsafe {
let head = ptr::read(whole.as_ptr() as _);
let tail = ptr::read(whole.as_ptr().offset(1) as _);
(head, tail)
}
}
}
/// Defines a `GenericSequence` that can be split into two parts at a given pivot index.
pub unsafe trait Split<T, K>: GenericSequence<T>
where
K: ArrayLength<T>,
{
/// First part of the resulting split array
type First: GenericSequence<T>;
/// Second part of the resulting split array
type Second: GenericSequence<T>;
/// Splits an array at the given index, returning the separate parts of the array.
fn split(self) -> (Self::First, Self::Second);
}
unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>
where
N: ArrayLength<T>,
K: ArrayLength<T>,
N: Sub<K>,
Diff<N, K>: ArrayLength<T>,
{
type First = GenericArray<T, K>;
type Second = GenericArray<T, Diff<N, K>>;
fn split(self) -> (Self::First, Self::Second) {
unsafe {
// ensure this doesn't get dropped
let whole = ManuallyDrop::new(self);
let head = ptr::read(whole.as_ptr() as *const _);
let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _);
(head, tail)
}
}
}
unsafe impl<'a, T, N, K> Split<T, K> for &'a GenericArray<T, N>
where
N: ArrayLength<T>,
K: ArrayLength<T> + 'static,
N: Sub<K>,
Diff<N, K>: ArrayLength<T>,
{
type First = &'a GenericArray<T, K>;
type Second = &'a GenericArray<T, Diff<N, K>>;
fn split(self) -> (Self::First, Self::Second) {
unsafe {
let ptr_to_first: *const T = self.as_ptr();
let head = &*(ptr_to_first as *const _);
let tail = &*(ptr_to_first.add(K::USIZE) as *const _);
(head, tail)
}
}
}
unsafe impl<'a, T, N, K> Split<T, K> for &'a mut GenericArray<T, N>
where
N: ArrayLength<T>,
K: ArrayLength<T> + 'static,
N: Sub<K>,
Diff<N, K>: ArrayLength<T>,
{
type First = &'a mut GenericArray<T, K>;
type Second = &'a mut GenericArray<T, Diff<N, K>>;
fn split(self) -> (Self::First, Self::Second) {
unsafe {
let ptr_to_first: *mut T = self.as_mut_ptr();
let head = &mut *(ptr_to_first as *mut _);
let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _);
(head, tail)
}
}
}
/// Defines `GenericSequence`s which can be joined together, forming a larger array.
pub unsafe trait Concat<T, M>: GenericSequence<T>
where
M: ArrayLength<T>,
{
/// Sequence to be concatenated with `self`
type Rest: GenericSequence<T, Length = M>;
/// Resulting sequence formed by the concatenation.
type Output: GenericSequence<T>;
/// Concatenate, or join, two sequences.
fn concat(self, rest: Self::Rest) -> Self::Output;
}
unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>
where
N: ArrayLength<T> + Add<M>,
M: ArrayLength<T>,
Sum<N, M>: ArrayLength<T>,
{
type Rest = GenericArray<T, M>;
type Output = GenericArray<T, Sum<N, M>>;
fn concat(self, rest: Self::Rest) -> Self::Output {
let mut output: MaybeUninit<Self::Output> = MaybeUninit::uninit();
let out_ptr = output.as_mut_ptr() as *mut Self;
unsafe {
// write all of self to the pointer
ptr::write(out_ptr, self);
// increment past self, then write the rest
ptr::write(out_ptr.add(1) as *mut _, rest);
output.assume_init()
}
}
}

View File

@@ -1,27 +1,27 @@
#[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");
}
#[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");
}

View File

@@ -1,98 +1,98 @@
#![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: S)
where
S: FunctionalSequence<i32>, // `.map`
S::Item: Add<i32, Output = i32>, // `x + 1`
S: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
MappedSequence<S, i32, i32>: 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, B>(a: A, b: B) -> i32
where
A: FunctionalSequence<i32>, // `.zip`
B: FunctionalSequence<i32, Length = A::Length>, // `.zip`
A: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
B: MappedGenericSequence<i32, i32, Mapped = MappedSequence<A, i32, i32>>, // `i32` -> `i32`, prove A and B can map to the same output
A::Item: Add<B::Item, Output = i32>, // `l + r`
MappedSequence<A, i32, i32>: MappedGenericSequence<i32, i32> + FunctionalSequence<i32>, // `.map`
SequenceItem<MappedSequence<A, i32, i32>>: Add<i32, Output=i32>, // `x + 1`
MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: Debug, // `println!`
MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: FunctionalSequence<i32>, // `.fold`
SequenceItem<MappedSequence<MappedSequence<A, i32, i32>, i32, i32>>: Add<i32, Output=i32> // `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<i32, U4>, b: GenericArray<i32, U4>) -> 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<N>(a: GenericArray<i32, N>, b: GenericArray<i32, N>) -> i32
where
N: ArrayLength<i32>,
{
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<T, N>(a: GenericArray<T, N>, b: GenericArray<T, N>) -> i32
where
N: ArrayLength<T> + ArrayLength<<T as Add<T>>::Output>,
T: Add<T, Output=i32>,
{
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<A, B, N: ArrayLength<A> + ArrayLength<B>>(a: GenericArray<A, N>, b: GenericArray<B, N>) -> i32
where
A: Add<B>,
N: ArrayLength<<A as Add<B>>::Output> +
ArrayLength<<<A as Add<B>>::Output as Add<i32>>::Output>,
<A as Add<B>>::Output: Add<i32>,
<<A as Add<B>>::Output as Add<i32>>::Output: Add<i32, Output=i32>,
{
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);
#![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: S)
where
S: FunctionalSequence<i32>, // `.map`
S::Item: Add<i32, Output = i32>, // `x + 1`
S: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
MappedSequence<S, i32, i32>: 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, B>(a: A, b: B) -> i32
where
A: FunctionalSequence<i32>, // `.zip`
B: FunctionalSequence<i32, Length = A::Length>, // `.zip`
A: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
B: MappedGenericSequence<i32, i32, Mapped = MappedSequence<A, i32, i32>>, // `i32` -> `i32`, prove A and B can map to the same output
A::Item: Add<B::Item, Output = i32>, // `l + r`
MappedSequence<A, i32, i32>: MappedGenericSequence<i32, i32> + FunctionalSequence<i32>, // `.map`
SequenceItem<MappedSequence<A, i32, i32>>: Add<i32, Output=i32>, // `x + 1`
MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: Debug, // `println!`
MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: FunctionalSequence<i32>, // `.fold`
SequenceItem<MappedSequence<MappedSequence<A, i32, i32>, i32, i32>>: Add<i32, Output=i32> // `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<i32, U4>, b: GenericArray<i32, U4>) -> 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<N>(a: GenericArray<i32, N>, b: GenericArray<i32, N>) -> i32
where
N: ArrayLength<i32>,
{
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<T, N>(a: GenericArray<T, N>, b: GenericArray<T, N>) -> i32
where
N: ArrayLength<T> + ArrayLength<<T as Add<T>>::Output>,
T: Add<T, Output=i32>,
{
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<A, B, N: ArrayLength<A> + ArrayLength<B>>(a: GenericArray<A, N>, b: GenericArray<B, N>) -> i32
where
A: Add<B>,
N: ArrayLength<<A as Add<B>>::Output> +
ArrayLength<<<A as Add<B>>::Output as Add<i32>>::Output>,
<A as Add<B>>::Output: Add<i32>,
<<A as Add<B>>::Output as Add<i32>>::Output: Add<i32, Output=i32>,
{
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);
}

View File

@@ -1,61 +1,61 @@
#[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::<u8, U2048>::default();
assert_eq!(format!("{:x}", ar), from_utf8(&[b'0'; 4096]).unwrap());
}
#[test]
fn long_lower_hex_truncated() {
let ar = GenericArray::<u8, U2048>::default();
assert_eq!(format!("{:.3001x}", ar), from_utf8(&[b'0'; 3001]).unwrap());
}
#[test]
fn long_upper_hex() {
let ar = GenericArray::<u8, U2048>::default();
assert_eq!(format!("{:X}", ar), from_utf8(&[b'0'; 4096]).unwrap());
}
#[test]
fn long_upper_hex_truncated() {
let ar = GenericArray::<u8, U2048>::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");
}
#[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::<u8, U2048>::default();
assert_eq!(format!("{:x}", ar), from_utf8(&[b'0'; 4096]).unwrap());
}
#[test]
fn long_lower_hex_truncated() {
let ar = GenericArray::<u8, U2048>::default();
assert_eq!(format!("{:.3001x}", ar), from_utf8(&[b'0'; 3001]).unwrap());
}
#[test]
fn long_upper_hex() {
let ar = GenericArray::<u8, U2048>::default();
assert_eq!(format!("{:X}", ar), from_utf8(&[b'0'; 4096]).unwrap());
}
#[test]
fn long_upper_hex_truncated() {
let ar = GenericArray::<u8, U2048>::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");
}

View File

@@ -1,10 +1,10 @@
#[macro_use]
extern crate generic_array as gen_arr;
use gen_arr::typenum;
#[test]
fn test_different_crate_name() {
let _: gen_arr::GenericArray<u32, typenum::U4> = arr![u32; 0, 1, 2, 3];
let _: gen_arr::GenericArray<u32, typenum::U0> = arr![u32;];
}
#[macro_use]
extern crate generic_array as gen_arr;
use gen_arr::typenum;
#[test]
fn test_different_crate_name() {
let _: gen_arr::GenericArray<u32, typenum::U4> = arr![u32; 0, 1, 2, 3];
let _: gen_arr::GenericArray<u32, typenum::U0> = arr![u32;];
}

View File

@@ -1,199 +1,199 @@
#[macro_use]
extern crate generic_array;
use std::cell::Cell;
use std::ops::Drop;
use generic_array::typenum::consts::U5;
use generic_array::GenericArray;
#[test]
fn test_from_iterator() {
struct BadExact(usize);
impl Iterator for BadExact {
type Item = usize;
fn next(&mut self) -> Option<usize> {
if self.0 == 1 {
return None;
}
self.0 -= 1;
Some(self.0)
}
}
impl ExactSizeIterator for BadExact {
fn len(&self) -> usize { self.0 }
}
assert!(GenericArray::<usize, U5>::from_exact_iter(BadExact(5)).is_none());
}
#[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<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
let v: Vec<i32> = 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_fold() {
assert_eq!(
arr![i32; 1, 2, 3, 4].into_iter().fold(0, |sum, x| sum + x),
10
);
let mut iter = arr![i32; 0, 1, 2, 3, 4, 5].into_iter();
iter.next();
iter.next_back();
assert_eq!(iter.clone().fold(0, |sum, x| sum + x), 10);
assert_eq!(iter.rfold(0, |sum, x| sum + x), 10);
}
#[test]
fn test_into_iter_drops() {
struct R<'a> {
i: &'a Cell<usize>,
}
impl<'a> Drop for R<'a> {
fn drop(&mut self) {
self.i.set(self.i.get() + 1);
}
}
fn r(i: &Cell<usize>) -> R {
R { i: i }
}
fn v(i: &Cell<usize>) -> GenericArray<R, U5> {
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
}
}
*/
#[macro_use]
extern crate generic_array;
use std::cell::Cell;
use std::ops::Drop;
use generic_array::typenum::consts::U5;
use generic_array::GenericArray;
#[test]
fn test_from_iterator() {
struct BadExact(usize);
impl Iterator for BadExact {
type Item = usize;
fn next(&mut self) -> Option<usize> {
if self.0 == 1 {
return None;
}
self.0 -= 1;
Some(self.0)
}
}
impl ExactSizeIterator for BadExact {
fn len(&self) -> usize { self.0 }
}
assert!(GenericArray::<usize, U5>::from_exact_iter(BadExact(5)).is_none());
}
#[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<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
let v: Vec<i32> = 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_fold() {
assert_eq!(
arr![i32; 1, 2, 3, 4].into_iter().fold(0, |sum, x| sum + x),
10
);
let mut iter = arr![i32; 0, 1, 2, 3, 4, 5].into_iter();
iter.next();
iter.next_back();
assert_eq!(iter.clone().fold(0, |sum, x| sum + x), 10);
assert_eq!(iter.rfold(0, |sum, x| sum + x), 10);
}
#[test]
fn test_into_iter_drops() {
struct R<'a> {
i: &'a Cell<usize>,
}
impl<'a> Drop for R<'a> {
fn drop(&mut self) {
self.i.set(self.i.get() + 1);
}
}
fn r(i: &Cell<usize>) -> R {
R { i: i }
}
fn v(i: &Cell<usize>) -> GenericArray<R, U5> {
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
}
}
*/

View File

@@ -1,379 +1,379 @@
#![recursion_limit = "128"]
#![no_std]
#[macro_use]
extern crate generic_array;
use core::cell::Cell;
use core::ops::{Add, Drop};
use generic_array::functional::*;
use generic_array::sequence::*;
use generic_array::typenum::{U0, U3, U4, U97};
use generic_array::GenericArray;
#[test]
fn test() {
let mut list97 = [0; 97];
for i in 0..97 {
list97[i] = i as i32;
}
let l: GenericArray<i32, U97> = 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<u32>);
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<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter),
TestDrop(&drop_counter),
TestDrop(&drop_counter)];
}
assert_eq!(drop_counter.get(), 3);
}
#[test]
fn test_arr() {
let test: GenericArray<u32, U3> = 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>(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::<u8, U4>::default();
assert_eq!(arr.as_slice(), &[0, 0, 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() {
let _ = 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::typenum::U6;
use generic_array::GenericArray;
#[test]
fn test_serde_implementation() {
let array: GenericArray<f64, U6> = 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<f64, U6> = serde_json::from_str(&string).unwrap();
assert_eq!(test_array, array);
}
}
#[test]
fn test_map() {
let b: GenericArray<i32, U4> = 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]);
}
#[allow(unused)]
#[derive(Debug, Copy, Clone)]
enum E {
V,
V2(i32),
V3 { h: bool, i: i32 },
}
#[allow(unused)]
#[derive(Debug, Copy, Clone)]
#[repr(C)]
#[repr(packed)]
struct Test {
t: u16,
s: u32,
mm: bool,
r: u16,
f: u16,
p: (),
o: u32,
ff: *const extern "C" fn(*const char) -> *const core::ffi::c_void,
l: *const core::ffi::c_void,
w: bool,
q: bool,
v: E,
}
#[test]
fn test_sizes() {
use core::mem::{size_of, size_of_val};
assert_eq!(size_of::<E>(), 8);
assert_eq!(size_of::<Test>(), 25 + size_of::<usize>() * 2);
assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::<u8>() * 3);
assert_eq!(size_of_val(&arr![u32; 1]), size_of::<u32>() * 1);
assert_eq!(size_of_val(&arr![u64; 1, 2, 3, 4]), size_of::<u64>() * 4);
assert_eq!(size_of::<GenericArray<Test, U97>>(), size_of::<Test>() * 97);
}
#[test]
fn test_alignment() {
use core::mem::align_of;
assert_eq!(align_of::<GenericArray::<u32, U0>>(), align_of::<[u32; 0]>());
assert_eq!(align_of::<GenericArray::<u32, U3>>(), align_of::<[u32; 3]>());
assert_eq!(align_of::<GenericArray::<Test, U3>>(), align_of::<[Test; 3]>());
}
#[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_split_ref() {
let a = arr![i32; 1, 2, 3, 4];
let a_ref = &a;
let (b_ref, c_ref) = a_ref.split();
assert_eq!(b_ref, &arr![i32; 1]);
assert_eq!(c_ref, &arr![i32; 2, 3, 4]);
let (e_ref, f_ref) = a_ref.split();
assert_eq!(e_ref, &arr![i32; 1, 2]);
assert_eq!(f_ref, &arr![i32; 3, 4]);
}
#[test]
fn test_split_mut() {
let mut a = arr![i32; 1, 2, 3, 4];
let a_ref = &mut a;
let (b_ref, c_ref) = a_ref.split();
assert_eq!(b_ref, &mut arr![i32; 1]);
assert_eq!(c_ref, &mut arr![i32; 2, 3, 4]);
let (e_ref, f_ref) = a_ref.split();
assert_eq!(e_ref, &mut arr![i32; 1, 2]);
assert_eq!(f_ref, &mut arr![i32; 3, 4]);
}
#[test]
fn test_concat() {
let a = arr![i32; 1, 2];
let b = arr![i32; 3, 4, 5];
let c = a.concat(b);
assert_eq!(c, arr![i32; 1, 2, 3, 4, 5]);
let (d, e) = c.split();
assert_eq!(d, arr![i32; 1, 2]);
assert_eq!(e, arr![i32; 3, 4, 5]);
}
#[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: S) -> i32
where
S: FunctionalSequence<i32>,
S::Item: Add<i32, Output = i32>, // `+`
i32: Add<S::Item, Output = i32>, // 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);
}
#[test]
fn test_as_ref() {
let a = arr![i32; 1, 2, 3, 4];
let a_ref: &[i32; 4] = a.as_ref();
assert_eq!(a_ref, &[1, 2, 3, 4]);
}
#[test]
fn test_as_mut() {
let mut a = arr![i32; 1, 2, 3, 4];
let a_mut: &mut [i32; 4] = a.as_mut();
assert_eq!(a_mut, &mut [1, 2, 3, 4]);
a_mut[2] = 0;
assert_eq!(a_mut, &mut [1, 2, 0, 4]);
assert_eq!(a, arr![i32; 1, 2, 0, 4]);
}
#[test]
fn test_from_array_ref() {
let a = arr![i32; 1, 2, 3, 4];
let a_ref: &[i32; 4] = a.as_ref();
let a_from: &GenericArray<i32, U4> = a_ref.into();
assert_eq!(&a, a_from);
}
#[test]
fn test_from_array_mut() {
let mut a = arr![i32; 1, 2, 3, 4];
let mut a_copy = a;
let a_mut: &mut [i32; 4] = a.as_mut();
let a_from: &mut GenericArray<i32, U4> = a_mut.into();
assert_eq!(&mut a_copy, a_from);
}
#![recursion_limit = "128"]
#![no_std]
#[macro_use]
extern crate generic_array;
use core::cell::Cell;
use core::ops::{Add, Drop};
use generic_array::functional::*;
use generic_array::sequence::*;
use generic_array::typenum::{U0, U3, U4, U97};
use generic_array::GenericArray;
#[test]
fn test() {
let mut list97 = [0; 97];
for i in 0..97 {
list97[i] = i as i32;
}
let l: GenericArray<i32, U97> = 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<u32>);
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<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter),
TestDrop(&drop_counter),
TestDrop(&drop_counter)];
}
assert_eq!(drop_counter.get(), 3);
}
#[test]
fn test_arr() {
let test: GenericArray<u32, U3> = 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>(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::<u8, U4>::default();
assert_eq!(arr.as_slice(), &[0, 0, 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() {
let _ = 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::typenum::U6;
use generic_array::GenericArray;
#[test]
fn test_serde_implementation() {
let array: GenericArray<f64, U6> = 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<f64, U6> = serde_json::from_str(&string).unwrap();
assert_eq!(test_array, array);
}
}
#[test]
fn test_map() {
let b: GenericArray<i32, U4> = 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]);
}
#[allow(unused)]
#[derive(Debug, Copy, Clone)]
enum E {
V,
V2(i32),
V3 { h: bool, i: i32 },
}
#[allow(unused)]
#[derive(Debug, Copy, Clone)]
#[repr(C)]
#[repr(packed)]
struct Test {
t: u16,
s: u32,
mm: bool,
r: u16,
f: u16,
p: (),
o: u32,
ff: *const extern "C" fn(*const char) -> *const core::ffi::c_void,
l: *const core::ffi::c_void,
w: bool,
q: bool,
v: E,
}
#[test]
fn test_sizes() {
use core::mem::{size_of, size_of_val};
assert_eq!(size_of::<E>(), 8);
assert_eq!(size_of::<Test>(), 25 + size_of::<usize>() * 2);
assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::<u8>() * 3);
assert_eq!(size_of_val(&arr![u32; 1]), size_of::<u32>() * 1);
assert_eq!(size_of_val(&arr![u64; 1, 2, 3, 4]), size_of::<u64>() * 4);
assert_eq!(size_of::<GenericArray<Test, U97>>(), size_of::<Test>() * 97);
}
#[test]
fn test_alignment() {
use core::mem::align_of;
assert_eq!(align_of::<GenericArray::<u32, U0>>(), align_of::<[u32; 0]>());
assert_eq!(align_of::<GenericArray::<u32, U3>>(), align_of::<[u32; 3]>());
assert_eq!(align_of::<GenericArray::<Test, U3>>(), align_of::<[Test; 3]>());
}
#[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_split_ref() {
let a = arr![i32; 1, 2, 3, 4];
let a_ref = &a;
let (b_ref, c_ref) = a_ref.split();
assert_eq!(b_ref, &arr![i32; 1]);
assert_eq!(c_ref, &arr![i32; 2, 3, 4]);
let (e_ref, f_ref) = a_ref.split();
assert_eq!(e_ref, &arr![i32; 1, 2]);
assert_eq!(f_ref, &arr![i32; 3, 4]);
}
#[test]
fn test_split_mut() {
let mut a = arr![i32; 1, 2, 3, 4];
let a_ref = &mut a;
let (b_ref, c_ref) = a_ref.split();
assert_eq!(b_ref, &mut arr![i32; 1]);
assert_eq!(c_ref, &mut arr![i32; 2, 3, 4]);
let (e_ref, f_ref) = a_ref.split();
assert_eq!(e_ref, &mut arr![i32; 1, 2]);
assert_eq!(f_ref, &mut arr![i32; 3, 4]);
}
#[test]
fn test_concat() {
let a = arr![i32; 1, 2];
let b = arr![i32; 3, 4, 5];
let c = a.concat(b);
assert_eq!(c, arr![i32; 1, 2, 3, 4, 5]);
let (d, e) = c.split();
assert_eq!(d, arr![i32; 1, 2]);
assert_eq!(e, arr![i32; 3, 4, 5]);
}
#[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: S) -> i32
where
S: FunctionalSequence<i32>,
S::Item: Add<i32, Output = i32>, // `+`
i32: Add<S::Item, Output = i32>, // 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);
}
#[test]
fn test_as_ref() {
let a = arr![i32; 1, 2, 3, 4];
let a_ref: &[i32; 4] = a.as_ref();
assert_eq!(a_ref, &[1, 2, 3, 4]);
}
#[test]
fn test_as_mut() {
let mut a = arr![i32; 1, 2, 3, 4];
let a_mut: &mut [i32; 4] = a.as_mut();
assert_eq!(a_mut, &mut [1, 2, 3, 4]);
a_mut[2] = 0;
assert_eq!(a_mut, &mut [1, 2, 0, 4]);
assert_eq!(a, arr![i32; 1, 2, 0, 4]);
}
#[test]
fn test_from_array_ref() {
let a = arr![i32; 1, 2, 3, 4];
let a_ref: &[i32; 4] = a.as_ref();
let a_from: &GenericArray<i32, U4> = a_ref.into();
assert_eq!(&a, a_from);
}
#[test]
fn test_from_array_mut() {
let mut a = arr![i32; 1, 2, 3, 4];
let mut a_copy = a;
let a_mut: &mut [i32; 4] = a.as_mut();
let a_from: &mut GenericArray<i32, U4> = a_mut.into();
assert_eq!(&mut a_copy, a_from);
}