diff options
Diffstat (limited to 'third_party/rust/generic-array')
-rw-r--r-- | third_party/rust/generic-array/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/generic-array/CHANGELOG.md | 98 | ||||
-rw-r--r-- | third_party/rust/generic-array/Cargo.toml | 75 | ||||
-rw-r--r-- | third_party/rust/generic-array/LICENSE | 21 | ||||
-rw-r--r-- | third_party/rust/generic-array/README.md | 62 | ||||
-rw-r--r-- | third_party/rust/generic-array/build.rs | 5 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/arr.rs | 125 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/functional.rs | 95 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/hex.rs | 105 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/impl_serde.rs | 108 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/impl_zeroize.rs | 25 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/impls.rs | 269 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/iter.rs | 251 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/lib.rs | 679 | ||||
-rw-r--r-- | third_party/rust/generic-array/src/sequence.rs | 380 |
15 files changed, 2299 insertions, 0 deletions
diff --git a/third_party/rust/generic-array/.cargo-checksum.json b/third_party/rust/generic-array/.cargo-checksum.json new file mode 100644 index 0000000000..f8ddf9aa70 --- /dev/null +++ b/third_party/rust/generic-array/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"e1d167ae44b01d58177842db72b8ddf754850756adc40ab87fef6af83ee7f759","Cargo.toml":"d75b1d3d662d67545bc43f331fdfbb95b8e9cb8522875608a7f8f2528e3325d3","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"9e86d03b400dc818f44df68b76dafd1d89e42a51221bcb0de4259a6529ab6d84","build.rs":"08fa30c4a2c1ad24fe5f987e721dfb20131f45ea5b5dc3e836dcf88a8e33248c","src/arr.rs":"c115d6926deb769ced772e9c4e1c84baf1bdea4fe4b9eb2061658a63869eab62","src/functional.rs":"7dd6ddd5db3000054cbbd76959f745c7de73c8493cbfb745be80509b306e4a83","src/hex.rs":"091fb78f6d373a6ef1c467d85c461472fcdb1e91efc294039f4c870151c3ee9f","src/impl_serde.rs":"f046daba067522b4c3e79437d04f43a001e83353c81e6b2188c37a2e63dba7a3","src/impl_zeroize.rs":"b7825efdc72890ed05337f7ebdfb27cc6952126f1c94c855fdafaa24fab0bf2a","src/impls.rs":"18b285821421eea0cdbbcfcc896eef67bd55d72f8d85b5827cca6687e9c0fc27","src/iter.rs":"4f50253f4130caa0780984b64467ca1916a881410f631f7eb85a1724b3ab4ced","src/lib.rs":"163b24f691d59383c9e347126569205b03272145334cbce037cd562b93ad9f30","src/sequence.rs":"26679cfec035bae7298f067f37e8d42a1eda8fe241e9cf2c2977ba4bddddab1d"},"package":"bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"}
\ No newline at end of file diff --git a/third_party/rust/generic-array/CHANGELOG.md b/third_party/rust/generic-array/CHANGELOG.md new file mode 100644 index 0000000000..f7e0766bc1 --- /dev/null +++ b/third_party/rust/generic-array/CHANGELOG.md @@ -0,0 +1,98 @@ +* **`0.14.6`**
+ * Add an optional `Zeroize` impl for `GenericArray` (#126 and #112)
+ * Cleanup some unsafe (#125) and typos (#114)
+ * Use `include` in `Cargo.toml` to reduce package size
+
+* **`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
diff --git a/third_party/rust/generic-array/Cargo.toml b/third_party/rust/generic-array/Cargo.toml new file mode 100644 index 0000000000..f04fc7bf73 --- /dev/null +++ b/third_party/rust/generic-array/Cargo.toml @@ -0,0 +1,75 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +name = "generic-array" +version = "0.14.6" +authors = [ + "Bartłomiej Kamiński <fizyk20@gmail.com>", + "Aaron Trent <novacrazy@gmail.com>", +] +include = [ + "src/**/*", + "LICENSE", + "README.md", + "CHANGELOG.md", + "build.rs", +] +description = "Generic types implementing functionality of arrays" +documentation = "http://fizyk20.github.io/generic-array/generic_array/" +readme = "README.md" +keywords = [ + "generic", + "array", +] +categories = [ + "data-structures", + "no-std", +] +license = "MIT" +repository = "https://github.com/fizyk20/generic-array.git" + +[package.metadata.docs.rs] +features = [ + "serde", + "zeroize", +] + +[lib] +name = "generic_array" + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.typenum] +version = "1.12" + +[dependencies.zeroize] +version = "1" +optional = true +default-features = false + +[dev-dependencies.bincode] +version = "1.0" + +[dev-dependencies.serde_json] +version = "1.0" + +[build-dependencies.version_check] +version = "0.9" + +[features] +more_lengths = [] + +[badges.travis-ci] +repository = "fizyk20/generic-array" diff --git a/third_party/rust/generic-array/LICENSE b/third_party/rust/generic-array/LICENSE new file mode 100644 index 0000000000..6d318946df --- /dev/null +++ b/third_party/rust/generic-array/LICENSE @@ -0,0 +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
+SOFTWARE.
\ No newline at end of file diff --git a/third_party/rust/generic-array/README.md b/third_party/rust/generic-array/README.md new file mode 100644 index 0000000000..cf54f40550 --- /dev/null +++ b/third_party/rust/generic-array/README.md @@ -0,0 +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);
+```
diff --git a/third_party/rust/generic-array/build.rs b/third_party/rust/generic-array/build.rs new file mode 100644 index 0000000000..c27c7e3fa9 --- /dev/null +++ b/third_party/rust/generic-array/build.rs @@ -0,0 +1,5 @@ +fn main() {
+ if version_check::is_min_version("1.41.0").unwrap_or(false) {
+ println!("cargo:rustc-cfg=relaxed_coherence");
+ }
+}
diff --git a/third_party/rust/generic-array/src/arr.rs b/third_party/rust/generic-array/src/arr.rs new file mode 100644 index 0000000000..cdcc038a3d --- /dev/null +++ b/third_party/rust/generic-array/src/arr.rs @@ -0,0 +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 {}
+}
diff --git a/third_party/rust/generic-array/src/functional.rs b/third_party/rust/generic-array/src/functional.rs new file mode 100644 index 0000000000..2ddcc5c4c4 --- /dev/null +++ b/third_party/rust/generic-array/src/functional.rs @@ -0,0 +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>,
+{
+}
diff --git a/third_party/rust/generic-array/src/hex.rs b/third_party/rust/generic-array/src/hex.rs new file mode 100644 index 0000000000..33c796f3c9 --- /dev/null +++ b/third_party/rust/generic-array/src/hex.rs @@ -0,0 +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(())
+ }
+}
diff --git a/third_party/rust/generic-array/src/impl_serde.rs b/third_party/rust/generic-array/src/impl_serde.rs new file mode 100644 index 0000000000..49c095a5de --- /dev/null +++ b/third_party/rust/generic-array/src/impl_serde.rs @@ -0,0 +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);
+ }
+
+}
diff --git a/third_party/rust/generic-array/src/impl_zeroize.rs b/third_party/rust/generic-array/src/impl_zeroize.rs new file mode 100644 index 0000000000..9937e4b150 --- /dev/null +++ b/third_party/rust/generic-array/src/impl_zeroize.rs @@ -0,0 +1,25 @@ +use {ArrayLength, GenericArray};
+
+use zeroize::Zeroize;
+
+#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]
+impl<T: Zeroize, N: ArrayLength<T>> Zeroize for GenericArray<T, N> {
+ fn zeroize(&mut self) {
+ self.as_mut_slice().iter_mut().zeroize()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_zeroize() {
+ let mut array = GenericArray::<u8, typenum::U2>::default();
+ array[0] = 4;
+ array[1] = 9;
+ array.zeroize();
+ assert_eq!(array[0], 0);
+ assert_eq!(array[1], 0);
+ }
+}
\ No newline at end of file diff --git a/third_party/rust/generic-array/src/impls.rs b/third_party/rust/generic-array/src/impls.rs new file mode 100644 index 0000000000..47ecc1d31d --- /dev/null +++ b/third_party/rust/generic-array/src/impls.rs @@ -0,0 +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
+}
diff --git a/third_party/rust/generic-array/src/iter.rs b/third_party/rust/generic-array/src/iter.rs new file mode 100644 index 0000000000..784ffa9068 --- /dev/null +++ b/third_party/rust/generic-array/src/iter.rs @@ -0,0 +1,251 @@ +//! `GenericArray` iterator implementation.
+
+use super::{ArrayLength, GenericArray};
+use core::iter::FusedIterator;
+use core::mem::ManuallyDrop;
+use core::{cmp, fmt, mem, ptr};
+
+/// 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.
+
+ let mut array = unsafe { ptr::read(&self.array) };
+ let mut index_back = 0;
+
+ for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {
+ unsafe { 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
diff --git a/third_party/rust/generic-array/src/lib.rs b/third_party/rust/generic-array/src/lib.rs new file mode 100644 index 0000000000..43ab26ff56 --- /dev/null +++ b/third_party/rust/generic-array/src/lib.rs @@ -0,0 +1,679 @@ +//! This crate implements a structure that can be used as a generic array type.
+//! Core Rust array types `[T; N]` can't be used generically with
+//! respect to `N`, so for example this:
+//!
+//! ```rust{compile_fail}
+//! struct Foo<T, N> {
+//! data: [T; N]
+//! }
+//! ```
+//!
+//! won't work.
+//!
+//! **generic-array** exports a `GenericArray<T,N>` type, which lets
+//! the above be implemented as:
+//!
+//! ```rust
+//! use generic_array::{ArrayLength, GenericArray};
+//!
+//! struct Foo<T, N: ArrayLength<T>> {
+//! data: GenericArray<T,N>
+//! }
+//! ```
+//!
+//! The `ArrayLength<T>` trait is implemented by default for
+//! [unsigned integer types](../typenum/uint/index.html) from
+//! [typenum](../typenum/index.html):
+//!
+//! ```rust
+//! # use generic_array::{ArrayLength, GenericArray};
+//! 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::{ArrayLength, GenericArray};
+//! 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()};
+//! # }
+//! ```
+//!
+//! For ease of use, an `arr!` macro is provided - example below:
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate generic_array;
+//! # extern crate typenum;
+//! # fn main() {
+//! let array = arr![u32; 1, 2, 3];
+//! assert_eq!(array[2], 3);
+//! # }
+//! ```
+
+#![deny(missing_docs)]
+#![deny(meta_variable_misuse)]
+#![no_std]
+
+#[cfg(feature = "serde")]
+extern crate serde;
+
+#[cfg(feature = "zeroize")]
+extern crate zeroize;
+
+#[cfg(test)]
+extern crate bincode;
+
+pub extern crate typenum;
+
+mod hex;
+mod impls;
+
+#[cfg(feature = "serde")]
+mod impl_serde;
+
+#[cfg(feature = "zeroize")]
+mod impl_zeroize;
+
+use core::iter::FromIterator;
+use core::marker::PhantomData;
+use core::mem::{MaybeUninit, ManuallyDrop};
+use core::ops::{Deref, DerefMut};
+use core::{mem, ptr, slice};
+use typenum::bit::{B0, B1};
+use typenum::uint::{UInt, UTerm, Unsigned};
+
+#[cfg_attr(test, macro_use)]
+pub mod arr;
+pub mod functional;
+pub mod iter;
+pub mod sequence;
+
+use self::functional::*;
+pub use self::iter::GenericArrayIter;
+use self::sequence::*;
+
+/// Trait making `GenericArray` work, marking types to be used as length of an array
+pub unsafe trait ArrayLength<T>: Unsigned {
+ /// Associated type representing the array type for the number
+ type ArrayType;
+}
+
+unsafe impl<T> ArrayLength<T> for UTerm {
+ #[doc(hidden)]
+ type ArrayType = [T; 0];
+}
+
+/// Internal type used to generate a struct of appropriate size
+#[allow(dead_code)]
+#[repr(C)]
+#[doc(hidden)]
+pub struct GenericArrayImplEven<T, U> {
+ parent1: U,
+ parent2: U,
+ _marker: PhantomData<T>,
+}
+
+impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
+ fn clone(&self) -> GenericArrayImplEven<T, U> {
+ GenericArrayImplEven {
+ parent1: self.parent1.clone(),
+ parent2: self.parent2.clone(),
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
+
+/// Internal type used to generate a struct of appropriate size
+#[allow(dead_code)]
+#[repr(C)]
+#[doc(hidden)]
+pub struct GenericArrayImplOdd<T, U> {
+ parent1: U,
+ parent2: U,
+ data: T,
+}
+
+impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
+ fn clone(&self) -> GenericArrayImplOdd<T, U> {
+ GenericArrayImplOdd {
+ parent1: self.parent1.clone(),
+ parent2: self.parent2.clone(),
+ data: self.data.clone(),
+ }
+ }
+}
+
+impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
+
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
+ #[doc(hidden)]
+ type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
+}
+
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
+ #[doc(hidden)]
+ type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
+}
+
+/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
+#[allow(dead_code)]
+#[repr(transparent)]
+pub struct GenericArray<T, U: ArrayLength<T>> {
+ data: U::ArrayType,
+}
+
+unsafe impl<T: Send, N: ArrayLength<T>> Send for GenericArray<T, N> {}
+unsafe impl<T: Sync, N: ArrayLength<T>> Sync for GenericArray<T, N> {}
+
+impl<T, N> Deref for GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ type Target = [T];
+
+ #[inline(always)]
+ fn deref(&self) -> &[T] {
+ unsafe { slice::from_raw_parts(self as *const Self as *const T, N::USIZE) }
+ }
+}
+
+impl<T, N> DerefMut for GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ #[inline(always)]
+ fn deref_mut(&mut self) -> &mut [T] {
+ unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::USIZE) }
+ }
+}
+
+/// Creates an array one element at a time using a mutable iterator
+/// you can write to with `ptr::write`.
+///
+/// Increment the position while iterating to mark off created elements,
+/// which will be dropped if `into_inner` is not called.
+#[doc(hidden)]
+pub struct ArrayBuilder<T, N: ArrayLength<T>> {
+ array: MaybeUninit<GenericArray<T, N>>,
+ position: usize,
+}
+
+impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
+ #[doc(hidden)]
+ #[inline]
+ pub unsafe fn new() -> ArrayBuilder<T, N> {
+ ArrayBuilder {
+ array: MaybeUninit::uninit(),
+ position: 0,
+ }
+ }
+
+ /// Creates a mutable iterator for writing to the array using `ptr::write`.
+ ///
+ /// Increment the position value given as a mutable reference as you iterate
+ /// to mark how many elements have been created.
+ #[doc(hidden)]
+ #[inline]
+ pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {
+ ((&mut *self.array.as_mut_ptr()).iter_mut(), &mut self.position)
+ }
+
+ /// When done writing (assuming all elements have been written to),
+ /// get the inner array.
+ #[doc(hidden)]
+ #[inline]
+ pub unsafe fn into_inner(self) -> GenericArray<T, N> {
+ let array = ptr::read(&self.array);
+
+ mem::forget(self);
+
+ array.assume_init()
+ }
+}
+
+impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
+ fn drop(&mut self) {
+ if mem::needs_drop::<T>() {
+ unsafe {
+ for value in &mut (&mut *self.array.as_mut_ptr())[..self.position] {
+ ptr::drop_in_place(value);
+ }
+ }
+ }
+ }
+}
+
+/// Consumes an array.
+///
+/// Increment the position while iterating and any leftover elements
+/// will be dropped if position does not go to N
+#[doc(hidden)]
+pub struct ArrayConsumer<T, N: ArrayLength<T>> {
+ array: ManuallyDrop<GenericArray<T, N>>,
+ position: usize,
+}
+
+impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
+ #[doc(hidden)]
+ #[inline]
+ pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
+ ArrayConsumer {
+ array: ManuallyDrop::new(array),
+ position: 0,
+ }
+ }
+
+ /// Creates an iterator and mutable reference to the internal position
+ /// to keep track of consumed elements.
+ ///
+ /// Increment the position as you iterate to mark off consumed elements
+ #[doc(hidden)]
+ #[inline]
+ pub unsafe fn iter_position(&mut self) -> (slice::Iter<T>, &mut usize) {
+ (self.array.iter(), &mut self.position)
+ }
+}
+
+impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
+ fn drop(&mut self) {
+ if mem::needs_drop::<T>() {
+ for value in &mut self.array[self.position..N::USIZE] {
+ unsafe {
+ ptr::drop_in_place(value);
+ }
+ }
+ }
+ }
+}
+
+impl<'a, T: 'a, N> IntoIterator for &'a GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ type IntoIter = slice::Iter<'a, T>;
+ type Item = &'a T;
+
+ fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {
+ self.as_slice().iter()
+ }
+}
+
+impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ type IntoIter = slice::IterMut<'a, T>;
+ type Item = &'a mut T;
+
+ fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {
+ self.as_mut_slice().iter_mut()
+ }
+}
+
+impl<T, N> FromIterator<T> for GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ fn from_iter<I>(iter: I) -> GenericArray<T, N>
+ where
+ I: IntoIterator<Item = T>,
+ {
+ unsafe {
+ let mut destination = ArrayBuilder::new();
+
+ {
+ let (destination_iter, position) = destination.iter_position();
+
+ iter.into_iter()
+ .zip(destination_iter)
+ .for_each(|(src, dst)| {
+ ptr::write(dst, src);
+
+ *position += 1;
+ });
+ }
+
+ if destination.position < N::USIZE {
+ from_iter_length_fail(destination.position, N::USIZE);
+ }
+
+ destination.into_inner()
+ }
+ }
+}
+
+#[inline(never)]
+#[cold]
+fn from_iter_length_fail(length: usize, expected: usize) -> ! {
+ panic!(
+ "GenericArray::from_iter received {} elements but expected {}",
+ length, expected
+ );
+}
+
+unsafe impl<T, N> GenericSequence<T> for GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+ Self: IntoIterator<Item = T>,
+{
+ type Length = N;
+ type Sequence = Self;
+
+ fn generate<F>(mut f: F) -> GenericArray<T, N>
+ where
+ F: FnMut(usize) -> T,
+ {
+ unsafe {
+ let mut destination = ArrayBuilder::new();
+
+ {
+ let (destination_iter, position) = destination.iter_position();
+
+ destination_iter.enumerate().for_each(|(i, dst)| {
+ ptr::write(dst, f(i));
+
+ *position += 1;
+ });
+ }
+
+ destination.into_inner()
+ }
+ }
+
+ #[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 mut right = ArrayConsumer::new(self);
+
+ let (left_array_iter, left_position) = left.iter_position();
+ let (right_array_iter, right_position) = right.iter_position();
+
+ FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {
+ let left_value = ptr::read(l);
+ let right_value = ptr::read(r);
+
+ *left_position += 1;
+ *right_position += 1;
+
+ f(left_value, right_value)
+ }))
+ }
+ }
+
+ #[doc(hidden)]
+ fn inverted_zip2<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,
+ {
+ unsafe {
+ let mut right = ArrayConsumer::new(self);
+
+ let (right_array_iter, right_position) = right.iter_position();
+
+ FromIterator::from_iter(
+ lhs.into_iter()
+ .zip(right_array_iter)
+ .map(|(left_value, r)| {
+ let right_value = ptr::read(r);
+
+ *right_position += 1;
+
+ f(left_value, right_value)
+ }),
+ )
+ }
+ }
+}
+
+unsafe impl<T, U, N> MappedGenericSequence<T, U> for GenericArray<T, N>
+where
+ N: ArrayLength<T> + ArrayLength<U>,
+ GenericArray<U, N>: GenericSequence<U, Length = N>,
+{
+ type Mapped = GenericArray<U, N>;
+}
+
+unsafe impl<T, N> FunctionalSequence<T> for GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+ Self: GenericSequence<T, Item = T, Length = N>,
+{
+ fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>
+ where
+ Self::Length: ArrayLength<U>,
+ Self: MappedGenericSequence<T, U>,
+ F: FnMut(T) -> U,
+ {
+ unsafe {
+ let mut source = ArrayConsumer::new(self);
+
+ let (array_iter, position) = source.iter_position();
+
+ FromIterator::from_iter(array_iter.map(|src| {
+ let value = ptr::read(src);
+
+ *position += 1;
+
+ f(value)
+ }))
+ }
+ }
+
+ #[inline]
+ fn zip<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(T, Rhs::Item) -> U,
+ {
+ rhs.inverted_zip(self, f)
+ }
+
+ fn fold<U, F>(self, init: U, mut f: F) -> U
+ where
+ F: FnMut(U, T) -> U,
+ {
+ unsafe {
+ let mut source = ArrayConsumer::new(self);
+
+ let (array_iter, position) = source.iter_position();
+
+ array_iter.fold(init, |acc, src| {
+ let value = ptr::read(src);
+
+ *position += 1;
+
+ f(acc, value)
+ })
+ }
+ }
+}
+
+impl<T, N> GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ /// Extracts a slice containing the entire array.
+ #[inline]
+ pub fn as_slice(&self) -> &[T] {
+ self.deref()
+ }
+
+ /// Extracts a mutable slice containing the entire array.
+ #[inline]
+ pub fn as_mut_slice(&mut self) -> &mut [T] {
+ self.deref_mut()
+ }
+
+ /// Converts slice to a generic array reference with inferred length;
+ ///
+ /// Length of the slice must be equal to the length of the array.
+ #[inline]
+ pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
+ slice.into()
+ }
+
+ /// Converts mutable slice to a mutable generic array reference
+ ///
+ /// Length of the slice must be equal to the length of the array.
+ #[inline]
+ pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
+ slice.into()
+ }
+}
+
+impl<'a, T, N: ArrayLength<T>> From<&'a [T]> for &'a GenericArray<T, N> {
+ /// Converts slice to a generic array reference with inferred length;
+ ///
+ /// Length of the slice must be equal to the length of the array.
+ #[inline]
+ fn from(slice: &[T]) -> &GenericArray<T, N> {
+ assert_eq!(slice.len(), N::USIZE);
+
+ unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
+ }
+}
+
+impl<'a, T, N: ArrayLength<T>> From<&'a mut [T]> for &'a mut GenericArray<T, N> {
+ /// Converts mutable slice to a mutable generic array reference
+ ///
+ /// Length of the slice must be equal to the length of the array.
+ #[inline]
+ fn from(slice: &mut [T]) -> &mut GenericArray<T, N> {
+ assert_eq!(slice.len(), N::USIZE);
+
+ unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
+ }
+}
+
+impl<T: Clone, N> GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ /// Construct a `GenericArray` from a slice by cloning its content
+ ///
+ /// Length of the slice must be equal to the length of the array
+ #[inline]
+ pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {
+ Self::from_exact_iter(list.iter().cloned())
+ .expect("Slice must be the same length as the array")
+ }
+}
+
+impl<T, N> GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ /// Creates a new `GenericArray` instance from an iterator with a specific size.
+ ///
+ /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`.
+ pub fn from_exact_iter<I>(iter: I) -> Option<Self>
+ where
+ I: IntoIterator<Item = T>,
+ {
+ let mut iter = iter.into_iter();
+
+ unsafe {
+ let mut destination = ArrayBuilder::new();
+
+ {
+ let (destination_iter, position) = destination.iter_position();
+
+ destination_iter.zip(&mut iter).for_each(|(dst, src)| {
+ ptr::write(dst, src);
+
+ *position += 1;
+ });
+
+ // The iterator produced fewer than `N` elements.
+ if *position != N::USIZE {
+ return None;
+ }
+
+ // The iterator produced more than `N` elements.
+ if iter.next().is_some() {
+ return None;
+ }
+ }
+
+ Some(destination.into_inner())
+ }
+ }
+}
+
+/// A reimplementation of the `transmute` function, avoiding problems
+/// when the compiler can't prove equal sizes.
+#[inline]
+#[doc(hidden)]
+pub unsafe fn transmute<A, B>(a: A) -> B {
+ let a = ManuallyDrop::new(a);
+ ::core::ptr::read(&*a as *const A as *const B)
+}
+
+#[cfg(test)]
+mod test {
+ // Compile with:
+ // cargo rustc --lib --profile test --release --
+ // -C target-cpu=native -C opt-level=3 --emit asm
+ // and view the assembly to make sure test_assembly generates
+ // SIMD instructions instead of a naive loop.
+
+ #[inline(never)]
+ pub fn black_box<T>(val: T) -> T {
+ use core::{mem, ptr};
+
+ let ret = unsafe { ptr::read_volatile(&val) };
+ mem::forget(val);
+ ret
+ }
+
+ #[test]
+ fn test_assembly() {
+ use crate::functional::*;
+
+ let a = black_box(arr![i32; 1, 3, 5, 7]);
+ let b = black_box(arr![i32; 2, 4, 6, 8]);
+
+ let c = (&a).zip(b, |l, r| l + r);
+
+ let d = a.fold(0, |a, x| a + x);
+
+ assert_eq!(c, arr![i32; 3, 7, 11, 15]);
+
+ assert_eq!(d, 16);
+ }
+}
diff --git a/third_party/rust/generic-array/src/sequence.rs b/third_party/rust/generic-array/src/sequence.rs new file mode 100644 index 0000000000..0119d3db67 --- /dev/null +++ b/third_party/rust/generic-array/src/sequence.rs @@ -0,0 +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()
+ }
+ }
+}
|