diff options
Diffstat (limited to 'vendor/generic-array')
22 files changed, 3600 insertions, 0 deletions
diff --git a/vendor/generic-array/.cargo-checksum.json b/vendor/generic-array/.cargo-checksum.json new file mode 100644 index 000000000..76861439f --- /dev/null +++ b/vendor/generic-array/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"0c2dc832f2f50aba2b59e4b28f045f5d9ed4d55763c9c9aed3891b715061aeff","Cargo.toml":"84096deb8ec081346988ab7bef7fc6a9e1e0796efcdd0ba8dcffa3beb26d1447","DESIGN.md":"8b745d89e634c48646202edfaa2151ee08a04a9c32271f4c2cc4afb63b4e952c","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"9e86d03b400dc818f44df68b76dafd1d89e42a51221bcb0de4259a6529ab6d84","build.rs":"08fa30c4a2c1ad24fe5f987e721dfb20131f45ea5b5dc3e836dcf88a8e33248c","rustfmt.toml":"13d771354ddee15d5aa5a168fd6965c3c0ee7aa7ce75cdd5e3b82852cdac5123","src/arr.rs":"c115d6926deb769ced772e9c4e1c84baf1bdea4fe4b9eb2061658a63869eab62","src/functional.rs":"7dd6ddd5db3000054cbbd76959f745c7de73c8493cbfb745be80509b306e4a83","src/hex.rs":"091fb78f6d373a6ef1c467d85c461472fcdb1e91efc294039f4c870151c3ee9f","src/impl_serde.rs":"f046daba067522b4c3e79437d04f43a001e83353c81e6b2188c37a2e63dba7a3","src/impls.rs":"18b285821421eea0cdbbcfcc896eef67bd55d72f8d85b5827cca6687e9c0fc27","src/iter.rs":"fa58bf5de00c900a767b3bdc9c9cdc49424bab55b2e3e2a88bd9445b06325f55","src/lib.rs":"22af14d446ec5f67a99e350d4a0c95e070f4ff9537ac9e84ec1172f654f8b95a","src/sequence.rs":"26679cfec035bae7298f067f37e8d42a1eda8fe241e9cf2c2977ba4bddddab1d","tests/arr.rs":"22d332fcb5e0314980ddc952af0265125cf53bb9cb8b546a9dcaec2e29bfc3b0","tests/generics.rs":"491c9351fd973ff2b7bc72e78d3069cf3ed3fcd2f9180558ab027099605fa147","tests/hex.rs":"fd428c2558da2f1e2cf229af2e40e5b35a2094b3306312ac41943d25a85b7de1","tests/import_name.rs":"c9439c7d7531ce79419b0d413d729ea4321887c091bd9be8b18e6c2413021ed0","tests/iter.rs":"d9f18c7a280a938a63d382086450146206c5805804d4b62c7e55cd60ea0e2d0d","tests/mod.rs":"556a9cb6f6699c523ebfb1b167a18b30d909604339e929e9c874da92aae60bd3"},"package":"fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"}
\ No newline at end of file diff --git a/vendor/generic-array/CHANGELOG.md b/vendor/generic-array/CHANGELOG.md new file mode 100644 index 000000000..cbd3355f1 --- /dev/null +++ b/vendor/generic-array/CHANGELOG.md @@ -0,0 +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
diff --git a/vendor/generic-array/Cargo.toml b/vendor/generic-array/Cargo.toml new file mode 100644 index 000000000..203a73f3a --- /dev/null +++ b/vendor/generic-array/Cargo.toml @@ -0,0 +1,45 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "generic-array" +version = "0.14.5" +authors = ["Bartłomiej Kamiński <fizyk20@gmail.com>", "Aaron Trent <novacrazy@gmail.com>"] +description = "Generic types implementing functionality of arrays" +documentation = "http://fizyk20.github.io/generic-array/generic_array/" +readme = "README.md" +keywords = ["generic", "array"] +categories = ["data-structures", "no-std"] +license = "MIT" +repository = "https://github.com/fizyk20/generic-array.git" + +[lib] +name = "generic_array" +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[dependencies.typenum] +version = "1.12" +[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/vendor/generic-array/DESIGN.md b/vendor/generic-array/DESIGN.md new file mode 100644 index 000000000..547bc7bd2 --- /dev/null +++ b/vendor/generic-array/DESIGN.md @@ -0,0 +1,585 @@ +Design and Usage Notes
+======================
+
+## Sections
+
+1. [How it Works](#how-it-works)
+2. [Initialization](#initialization)
+3. [Functional Programming](#functional-programming)
+4. [Miscellaneous Utilities](#miscellaneous-utilities)
+5. [Safety](#safety)
+6. [Optimization](#optimization)
+7. [The Future](#the-future)
+
+**NOTE**: This document uses `<details>` sections, so look out for collapsible parts with an arrow on the left.
+
+# How it works
+
+`generic-array` is a method of achieving fixed-length fixed-size stack-allocated generic arrays without needing const generics in stable Rust.
+
+That is to say this:
+
+```rust
+struct Foo<const N: usize> {
+ data: [i32; N],
+}
+```
+
+or anything similar is not currently supported.
+
+However, Rust's type system is sufficiently advanced, and a "hack" for solving this was created in the form of the `typenum` crate, which recursively defines integer values in binary as nested types, and operations which can be applied to those type-numbers, such as `Add`, `Sub`, etc.
+
+e.g. `6` would be `UInt<UInt<UInt<UTerm, B1>, B1>, B0>`
+
+Over time, I've come to see `typenum` as less of a hack and more as an elegant solution.
+
+The recursive binary nature of `typenum` is what makes `generic-array` possible, so:
+
+```rust
+struct Foo<N: ArrayLength<i32>> {
+ data: GenericArray<i32, N>,
+}
+```
+
+is supported.
+
+I often see questions about why `ArrayLength` requires the element type `T` in it's signature, even though it's not used in the inner `ArrayType`.
+
+This is because `GenericArray` itself does not define the actual array. Rather, it is defined as:
+
+```rust
+pub struct GenericArray<T, N: ArrayLength<T>> {
+ data: N::ArrayType,
+}
+```
+
+The trait `ArrayLength` does all the real heavy lifting for defining the data, with implementations on `UInt<N, B0>`, `UInt<N, B1>` and `UTerm`, which correspond to even, odd and zero numeric values, respectively.
+
+`ArrayLength`'s implementations use type-level recursion to peel away each least significant bit and form sort of an opaque binary tree of contiguous data the correct physical size to store `N` elements of `T`. The tree, or block of data, is then stored inside of `GenericArray` to be reinterpreted as the array.
+
+For example, `GenericArray<T, U6>` more or less expands to (at compile time):
+
+<details>
+<summary>Expand for code</summary>
+
+```rust
+GenericArray {
+ // UInt<UInt<UInt<UTerm, B1>, B1>, B0>
+ data: EvenData {
+ // UInt<UInt<UTerm, B1>, B1>
+ left: OddData {
+ // UInt<UTerm, B1>
+ left: OddData {
+ left: (), // UTerm
+ right: (), // UTerm
+ data: T, // Element 0
+ },
+ // UInt<UTerm, B1>
+ right: OddData {
+ left: (), // UTerm
+ right: (), // UTerm
+ data: T, // Element 1
+ },
+ data: T // Element 2
+ },
+ // UInt<UInt<UTerm, B1>, B1>
+ right: OddData {
+ // UInt<UTerm, B1>
+ left: OddData {
+ left: (), // UTerm
+ right: (), // UTerm
+ data: T, // Element 3
+ },
+ // UInt<UTerm, B1>
+ right: OddData {
+ left: (), // UTerm
+ right: (), // UTerm
+ data: T, // Element 4
+ },
+ data: T // Element 5
+ }
+ }
+}
+```
+
+</details>
+
+This has the added benefit of only being `log2(N)` deep, which is important for things like `Drop`, which we'll go into later.
+
+Then, we take `data` and cast it to `*const T` or `*mut T` and use it as a slice like:
+
+```rust
+unsafe {
+ slice::from_raw_parts(
+ self as *const Self as *const T,
+ N::to_usize()
+ )
+}
+```
+
+It is useful to note that because `typenum` is compile-time with nested generics, `to_usize`, even if it isn't a `const fn`, *does* expand to effectively `1 + 2 + 4 + 8 + ...` and so forth, which LLVM is smart enough to reduce to a single compile-time constant. This helps hint to the optimizers about things such as bounds checks.
+
+So, to reiterate, we're working with a raw block of contiguous memory the correct physical size to store `N` elements of `T`. It's really no different from how normal arrays are stored.
+
+## Pointer Safety
+
+Of course, casting pointers around and constructing blocks of data out of thin air is normal for C, but here in Rust we try to be a bit less prone to segfaults. Therefore, great care is taken to minimize casual `unsafe` usage and restrict `unsafe` to specific parts of the API, making heavy use those exposed safe APIs internally.
+
+For example, the above `slice::from_raw_parts` is only used twice in the entire library, once for `&[T]` and `slice::from_raw_parts_mut` once for `&mut [T]`. Everything else goes through those slices.
+
+# Initialization
+
+## Constant
+
+"Constant" initialization, that is to say - without dynamic values, can be done via the `arr![]` macro, which works almost exactly like `vec![]`, but with an additional type parameter.
+
+Example:
+
+```rust
+let my_arr = arr![i32; 1, 2, 3, 4, 5, 6, 7, 8];
+```
+
+## Dynamic
+
+Although some users have opted to use their own initializers, as of version `0.9` and beyond `generic-array` includes safe methods for initializing elements in the array.
+
+The `GenericSequence` trait defines a `generate` method which can be used like so:
+
+```rust
+use generic_array::{GenericArray, sequence::GenericSequence};
+
+let squares: GenericArray<i32, U4> =
+ GenericArray::generate(|i: usize| i as i32 * 2);
+```
+
+and `GenericArray` additionally implements `FromIterator`, although `from_iter` ***will*** panic if the number of elements is not *at least* `N`. It will ignore extra items.
+
+The safety of these operations is described later.
+
+# Functional Programming
+
+In addition to `GenericSequence`, this crate provides a `FunctionalSequence`, which allows extremely efficient `map`, `zip` and `fold` operations on `GenericArray`s.
+
+As described at the end of the [Optimization](#optimization) section, `FunctionalSequence` uses clever specialization tactics to provide optimized methods wherever possible, while remaining perfectly safe.
+
+Some examples, taken from `tests/generic.rs`:
+
+<details>
+<summary>Expand for code</summary>
+
+This is so extensive to show how you can build up to processing totally arbitrary sequences, but for the most part these can be used on `GenericArray` instances without much added complexity.
+
+```rust
+/// 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)
+}
+```
+</details>
+
+and if you really want to go off the deep end and support any arbitrary *`GenericSequence`*:
+
+<details>
+<summary>Expand for code</summary>
+
+```rust
+/// 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)
+}
+```
+
+of course, as I stated before, that's almost never necessary, especially when you know the concrete types of all the components.
+
+</details>
+
+The [`numeric-array`](https://crates.io/crates/numeric-array) crate uses these to apply numeric operations across all elements in a `GenericArray`, making full use of all the optimizations described in the last section here.
+
+# Miscellaneous Utilities
+
+Although not usually advertised, `generic-array` contains traits for lengthening, shortening, splitting and concatenating arrays.
+
+For example, these snippets are taken from `tests/mod.rs`:
+
+<details>
+<summary>Expand for code</summary>
+
+Appending and prepending elements:
+
+```rust
+use generic_array::sequence::Lengthen;
+
+#[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]);
+}
+```
+
+Popping elements from the front of back of the array:
+
+```rust
+use generic_array::sequence::Shorten;
+
+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]);
+```
+
+and of course concatenating and splitting:
+
+```rust
+use generic_array::sequence::{Concat, Split};
+
+let a = arr![i32; 1, 2];
+let b = arr![i32; 3, 4];
+
+let c = a.concat(b);
+
+assert_eq!(c, arr![i32; 1, 2, 3, 4]);
+
+let (d, e) = c.split();
+
+assert_eq!(d, arr![i32; 1]);
+assert_eq!(e, arr![i32; 2, 3, 4]);
+```
+</details>
+
+`Split` and `Concat` in these examples use type-inference to determine the lengths of the resulting arrays.
+
+# Safety
+
+As stated earlier, for raw reinterpretations such as this, safety is a must even while working with unsafe code. Great care is taken to reduce or eliminate undefined behavior.
+
+For most of the above code examples, the biggest potential undefined behavior hasn't even been applicable for one simple reason: they were all primitive values.
+
+The simplest way to lead into this is to post these questions:
+
+1. What if the element type of the array implements `Drop`?
+2. What if `GenericArray::generate` opens a bunch of files?
+3. What if halfway through opening each of the files, one is not found?
+4. What if the resulting error is unwrapped, causing the generation function to panic?
+
+For a fully initialized `GenericArray`, the expanded structure as described in the [How It Works](#how-it-works) can implement `Drop` naturally, recursively dropping elements. As it is only `log2(N)` deep, the recursion is very small overall.
+
+In fact, I tested it while writing this, the size of the array itself overflows the stack before any recursive calls to `drop` can.
+
+However, ***partially*** initialized arrays, such as described in the above hypothetical, pose an issue where `drop` could be called on uninitialized data, which is undefined behavior.
+
+To solve this, `GenericArray` implements two components named `ArrayBuilder` and `ArrayConsumer`, which work very similarly.
+
+`ArrayBuilder` creates a block of wholly uninitialized memory via `mem::unintialized()`, and stores that in a `ManuallyDrop` wrapper. `ManuallyDrop` does exactly what it says on the tin, and simply doesn't drop the value unless manually requested to.
+
+So, as we're initializing our array, `ArrayBuilder` keeps track of the current position through it, and if something happens, `ArrayBuilder` itself will iteratively and manually `drop` all currently initialized elements, ignoring any uninitialized ones, because those are just raw memory and should be ignored.
+
+`ArrayConsumer` does almost the same, "moving" values out of the array and into something else, like user code. It uses `ptr::read` to "move" the value out, and increments a counter saying that value is no longer valid in the array.
+
+If a panic occurs in the user code with that element, it's dropped naturally as it was moved into that scope. `ArrayConsumer` then proceeds to iteratively and manually `drop` all *remaining* elements.
+
+Combined, these two systems provide a safe system for building and consuming `GenericArray`s. In fact, they are used extensively inside the library itself for `FromIterator`, `GenericSequence` and `FunctionalSequence`, among others.
+
+Even `GenericArray`s implementation of `Clone` makes use of this via:
+
+```rust
+impl<T: Clone, N> Clone for GenericArray<T, N>
+where
+ N: ArrayLength<T>,
+{
+ fn clone(&self) -> GenericArray<T, N> {
+ self.map(|x| x.clone())
+ }
+}
+```
+
+where `.map` is from the `FunctionalSequence`, and uses those builder and consumer structures to safely move and initialize values. Although, in this particular case, a consumer is not necessary as we're using references. More on how that is automatically deduced is described in the next section.
+
+# Optimization
+
+Rust and LLVM is smart. Crazy smart. However, it's not magic.
+
+In my experience, most of Rust's "zero-cost" abstractions stem more from the type system, rather than explicit optimizations. Most Rust code is very easily optimizable and inlinable by design, so it can be simplified and compacted rather well, as opposed to the spaghetti code of some other languages.
+
+Unfortunately, unless `rustc` or LLVM can "prove" things about code to simplify it, it must still be run, and can prevent further optimization.
+
+A great example of this, and why I created the `GenericSequence` and `FunctionalSequence` traits, are iterators.
+
+Custom iterators are slow. Not terribly slow, but slow enough to prevent some rather important optimizations.
+
+Take `GenericArrayIter` for example:
+
+<details>
+<summary>Expand for code</summary>
+
+```rust
+pub struct GenericArrayIter<T, N: ArrayLength<T>> {
+ array: ManuallyDrop<GenericArray<T, N>>,
+ index: usize,
+ index_back: usize,
+}
+
+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
+ }
+ }
+
+ //and more
+}
+```
+</details>
+
+Seems simple enough, right? Move an element out of the array with `ptr::read` and increment the index. If the iterator is dropped, the remaining elements are dropped exactly as they would with `ArrayConsumer`. `index_back` is provided for `DoubleEndedIterator`.
+
+Unfortunately, that single `if` statement is terrible. In my mind, this is one of the biggest flaws of the iterator design. A conditional jump on a mutable variable unrelated to the data we are accessing on each call foils the optimizer and generates suboptimal code for the above iterator, even when we use `get_unchecked`.
+
+The optimizer is unable to see that we are simply accessing memory sequentially. In fact, almost all iterators are like this. Granted, this is usually fine and, especially if they have to handle errors, it's perfectly acceptable.
+
+However, there is one iterator in the standard library that is optimized perfectly: the slice iterator. So perfectly in fact that it allows the optimizer to do something even more special: **auto-vectorization**! We'll get to that later.
+
+It's a bit frustrating as to *why* slice iterators can be so perfectly optimized, and it basically boils down to that the iterator itself does not own the data the slice refers to, so it uses raw pointers to the array/sequence/etc. rather than having to use an index on a stack allocated and always moving array. It can check for if the iterator is empty by comparing some `front` and `back` pointers for equality, and because those directly correspond to the position in memory of the next element, LLVM can see that and make optimizations.
+
+So, the gist of that is: always use slice iterators where possible.
+
+Here comes the most important part of all of this: `ArrayBuilder` and `ArrayConsumer` don't iterate the arrays themselves. Instead, we use slice iterators (immutable and mutable), with `zip` or `enumerate`, to apply operations to the entire array, incrementing the position in both `ArrayBuilder` or `ArrayConsumer` to keep track.
+
+For example, `GenericSequence::generate` for `GenericArray` is:
+
+<details>
+<summary>Expand for code</summary>
+
+```rust
+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();
+
+ for (i, dst) in destination_iter.enumerate() {
+ ptr::write(dst, f(i));
+
+ *position += 1;
+ }
+ }
+
+ destination.into_inner()
+ }
+}
+```
+
+where `ArrayBuilder::iter_position` is just an internal convenience function:
+
+```rust
+pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {
+ (self.array.iter_mut(), &mut self.position)
+}
+```
+</details>
+
+Of course, this may appear to be redundant, if we're using an iterator that keeps track of the position itself, and the builder is also keeping track of the position. However, the two are decoupled.
+
+If the generation function doesn't have a chance at panicking, and/or the array element type doesn't implement `Drop`, the optimizer deems the `Drop` implementation on `ArrayBuilder` (and `ArrayConsumer`) dead code, and therefore `position` is never actually read from, so it becomes dead code as well, and is removed.
+
+So for simple non-`Drop`/non-panicking elements and generation functions, `generate` becomes a very simple loop that uses a slice iterator to write values to the array.
+
+Next, let's take a look at a more complex example where this *really* shines: `.zip`
+
+To cut down on excessively verbose code, `.zip` uses `FromIterator` for building the array, which has almost identical code to `generate`, so it will be omitted.
+
+The first implementation of `.zip` is defined as:
+
+<details>
+<summary>Expand for code</summary>
+
+```rust
+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)
+ }))
+ }
+}
+```
+</details>
+
+The gist of this is that we have two `GenericArray` instances that need to be zipped together and mapped to a new sequence. This employs two `ArrayConsumer`s, and more or less use the same pattern as the previous example.
+
+Again, the position values can be optimized out, and so can the slice iterator adapters.
+
+We can go a step further with this, however.
+
+Consider this:
+
+```rust
+let a = arr![i32; 1, 3, 5, 7];
+let b = arr![i32; 2, 4, 6, 8];
+
+let c = a.zip(b, |l, r| l + r);
+
+assert_eq!(c, arr![i32; 3, 7, 11, 15]);
+```
+
+when compiled with:
+
+```
+cargo rustc --lib --profile test --release -- -C target-cpu=native -C opt-level=3 --emit asm
+```
+
+will produce assembly with the following relevant instructions taken from the entire program:
+
+```asm
+; Copy constant to register
+vmovaps __xmm@00000007000000050000000300000001(%rip), %xmm0
+
+; Copy constant to register
+vmovaps __xmm@00000008000000060000000400000002(%rip), %xmm0
+
+; Add the two values together
+vpaddd 192(%rsp), %xmm0, %xmm1
+
+; Copy constant to register
+vmovaps __xmm@0000000f0000000b0000000700000003(%rip), %xmm0
+
+; Compare result of the addition with the last constant
+vpcmpeqb 128(%rsp), %xmm0, %xmm0
+```
+
+so, aside from a bunch of obvious hygiene instructions around those selected instructions,
+it seriously boils down that `.zip` call to a ***SINGLE*** SIMD instruction. In fact, it continues to do this for even larger arrays. Although it does fall back to individual additions for fewer than four elements, as it can't fit those into an SSE register evenly.
+
+Using this property of auto-vectorization without sacrificing safety, I created the [`numeric-array`](https://crates.io/crates/numeric-array) crate which makes use of this to wrap `GenericArray` and implement numeric traits so that almost *all* operations can be auto-vectorized, even complex ones like fused multiple-add.
+
+It doesn't end there, though. You may have noticed that the function name for zip above wasn't `zip`, but `inverted_zip`.
+
+This is because `generic-array` employs a clever specialization tactic to ensure `.zip` works corrects with:
+
+1. `a.zip(b, ...)`
+2. `(&a).zip(b, ...)`
+3. `(&a).zip(&b, ...)`
+4. `a.zip(&b, ...)`
+
+wherein `GenericSequence` and `FunctionalSequence` have default implementations of `zip` variants, with concrete implementations for `GenericArray`. As `GenericSequence` is implemented for `&GenericArray`, where calling `into_iter` on produces a slice iterator, it can use "naive" iterator adapters to the same effect, while the specialized implementations use `ArrayConsumer`.
+
+The result is that any combination of move or reference calls to `.zip`, `.map` and `.fold` produce code that can be optimized, none of them falling back to slow non-slice iterators. All perfectly safe with the `ArrayBuilder` and `ArrayConsumer` systems.
+
+Honestly, `GenericArray` is better than standard arrays at this point.
+
+# The Future
+
+If/when const generics land in stable Rust, my intention is to reorient this crate or create a new crate to provide traits and wrappers for standard arrays to provide the same safety and performance discussed above.
\ No newline at end of file diff --git a/vendor/generic-array/LICENSE b/vendor/generic-array/LICENSE new file mode 100644 index 000000000..6d318946d --- /dev/null +++ b/vendor/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/vendor/generic-array/README.md b/vendor/generic-array/README.md new file mode 100644 index 000000000..cf54f4055 --- /dev/null +++ b/vendor/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/vendor/generic-array/build.rs b/vendor/generic-array/build.rs new file mode 100644 index 000000000..c27c7e3fa --- /dev/null +++ b/vendor/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/vendor/generic-array/rustfmt.toml b/vendor/generic-array/rustfmt.toml new file mode 100644 index 000000000..a46e4b2bd --- /dev/null +++ b/vendor/generic-array/rustfmt.toml @@ -0,0 +1,3 @@ +reorder_imports = true
+reorder_imported_names = true
+use_try_shorthand = true
diff --git a/vendor/generic-array/src/arr.rs b/vendor/generic-array/src/arr.rs new file mode 100644 index 000000000..cdcc038a3 --- /dev/null +++ b/vendor/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/vendor/generic-array/src/functional.rs b/vendor/generic-array/src/functional.rs new file mode 100644 index 000000000..2ddcc5c4c --- /dev/null +++ b/vendor/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/vendor/generic-array/src/hex.rs b/vendor/generic-array/src/hex.rs new file mode 100644 index 000000000..33c796f3c --- /dev/null +++ b/vendor/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/vendor/generic-array/src/impl_serde.rs b/vendor/generic-array/src/impl_serde.rs new file mode 100644 index 000000000..49c095a5d --- /dev/null +++ b/vendor/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/vendor/generic-array/src/impls.rs b/vendor/generic-array/src/impls.rs new file mode 100644 index 000000000..47ecc1d31 --- /dev/null +++ b/vendor/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/vendor/generic-array/src/iter.rs b/vendor/generic-array/src/iter.rs new file mode 100644 index 000000000..fbf0e9802 --- /dev/null +++ b/vendor/generic-array/src/iter.rs @@ -0,0 +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
diff --git a/vendor/generic-array/src/lib.rs b/vendor/generic-array/src/lib.rs new file mode 100644 index 000000000..4e634448a --- /dev/null +++ b/vendor/generic-array/src/lib.rs @@ -0,0 +1,673 @@ +//! 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(test)]
+extern crate bincode;
+
+pub extern crate typenum;
+
+mod hex;
+mod impls;
+
+#[cfg(feature = "serde")]
+mod impl_serde;
+
+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`.
+///
+/// Incremenent the position while iterating to mark off created elements,
+/// which will be dropped if `into_inner` is not called.
+#[doc(hidden)]
+pub struct ArrayBuilder<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 niave 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/vendor/generic-array/src/sequence.rs b/vendor/generic-array/src/sequence.rs new file mode 100644 index 000000000..0119d3db6 --- /dev/null +++ b/vendor/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()
+ }
+ }
+}
diff --git a/vendor/generic-array/tests/arr.rs b/vendor/generic-array/tests/arr.rs new file mode 100644 index 000000000..461805a50 --- /dev/null +++ b/vendor/generic-array/tests/arr.rs @@ -0,0 +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");
+}
diff --git a/vendor/generic-array/tests/generics.rs b/vendor/generic-array/tests/generics.rs new file mode 100644 index 000000000..952867b38 --- /dev/null +++ b/vendor/generic-array/tests/generics.rs @@ -0,0 +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);
+}
\ No newline at end of file diff --git a/vendor/generic-array/tests/hex.rs b/vendor/generic-array/tests/hex.rs new file mode 100644 index 000000000..0c63391a6 --- /dev/null +++ b/vendor/generic-array/tests/hex.rs @@ -0,0 +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");
+}
diff --git a/vendor/generic-array/tests/import_name.rs b/vendor/generic-array/tests/import_name.rs new file mode 100644 index 000000000..f59f1b6c5 --- /dev/null +++ b/vendor/generic-array/tests/import_name.rs @@ -0,0 +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;];
+}
diff --git a/vendor/generic-array/tests/iter.rs b/vendor/generic-array/tests/iter.rs new file mode 100644 index 000000000..d96f98414 --- /dev/null +++ b/vendor/generic-array/tests/iter.rs @@ -0,0 +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
+ }
+}
+*/
diff --git a/vendor/generic-array/tests/mod.rs b/vendor/generic-array/tests/mod.rs new file mode 100644 index 000000000..fb1a35f2c --- /dev/null +++ b/vendor/generic-array/tests/mod.rs @@ -0,0 +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);
+}
|