summaryrefslogtreecommitdiffstats
path: root/vendor/generic-array-0.14.4
diff options
context:
space:
mode:
authorEllie Huxtable <e@elm.sh>2021-05-17 19:51:09 +0100
committerEllie Huxtable <e@elm.sh>2021-05-17 19:51:09 +0100
commitd0215a937a7889a97e11778ee4b0f9a12de01278 (patch)
tree5a8fd5ad62e6b5a4c218746ff2d4bd97373a48de /vendor/generic-array-0.14.4
parent802a2258cbd839c5b82d24f74d7aebe4a27d8dc5 (diff)
Vendor dependenciesvendor
Just testing how CI works with this. I tend to prefer vendoring, as it means that if you have a copy of the code *you can always build it*. Even if you're 20 years in the future This is the output of ``` cargo vendor --versioned-dirs ```
Diffstat (limited to 'vendor/generic-array-0.14.4')
-rw-r--r--vendor/generic-array-0.14.4/.cargo-checksum.json1
-rw-r--r--vendor/generic-array-0.14.4/CHANGELOG.md90
-rw-r--r--vendor/generic-array-0.14.4/Cargo.toml45
-rw-r--r--vendor/generic-array-0.14.4/DESIGN.md585
-rw-r--r--vendor/generic-array-0.14.4/LICENSE21
-rw-r--r--vendor/generic-array-0.14.4/README.md62
-rw-r--r--vendor/generic-array-0.14.4/build.rs5
-rw-r--r--vendor/generic-array-0.14.4/rustfmt.toml3
-rw-r--r--vendor/generic-array-0.14.4/src/arr.rs125
-rw-r--r--vendor/generic-array-0.14.4/src/functional.rs95
-rw-r--r--vendor/generic-array-0.14.4/src/hex.rs105
-rw-r--r--vendor/generic-array-0.14.4/src/impl_serde.rs108
-rw-r--r--vendor/generic-array-0.14.4/src/impls.rs269
-rw-r--r--vendor/generic-array-0.14.4/src/iter.rs257
-rw-r--r--vendor/generic-array-0.14.4/src/lib.rs673
-rw-r--r--vendor/generic-array-0.14.4/src/sequence.rs380
-rw-r--r--vendor/generic-array-0.14.4/tests/arr.rs27
-rw-r--r--vendor/generic-array-0.14.4/tests/generics.rs98
-rw-r--r--vendor/generic-array-0.14.4/tests/hex.rs61
-rw-r--r--vendor/generic-array-0.14.4/tests/import_name.rs10
-rw-r--r--vendor/generic-array-0.14.4/tests/iter.rs199
-rw-r--r--vendor/generic-array-0.14.4/tests/mod.rs379
22 files changed, 3598 insertions, 0 deletions
diff --git a/vendor/generic-array-0.14.4/.cargo-checksum.json b/vendor/generic-array-0.14.4/.cargo-checksum.json
new file mode 100644
index 00000000..9996cc45
--- /dev/null
+++ b/vendor/generic-array-0.14.4/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"6fd290755dcbb7da68223425151b556fd76ab9998fe9cee81042acf1a47164e5","Cargo.toml":"a14186cc9cbb4d0446fcb8898439c24b5dd8acccc05dd27e3d829c069da97fa4","DESIGN.md":"8b745d89e634c48646202edfaa2151ee08a04a9c32271f4c2cc4afb63b4e952c","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"9e86d03b400dc818f44df68b76dafd1d89e42a51221bcb0de4259a6529ab6d84","build.rs":"08fa30c4a2c1ad24fe5f987e721dfb20131f45ea5b5dc3e836dcf88a8e33248c","rustfmt.toml":"13d771354ddee15d5aa5a168fd6965c3c0ee7aa7ce75cdd5e3b82852cdac5123","src/arr.rs":"a898e3a37910bfc59d9caf71bf22eda02d3a4ad96c75f8a6d49ed1309531aa4e","src/functional.rs":"7dd6ddd5db3000054cbbd76959f745c7de73c8493cbfb745be80509b306e4a83","src/hex.rs":"091fb78f6d373a6ef1c467d85c461472fcdb1e91efc294039f4c870151c3ee9f","src/impl_serde.rs":"f046daba067522b4c3e79437d04f43a001e83353c81e6b2188c37a2e63dba7a3","src/impls.rs":"18b285821421eea0cdbbcfcc896eef67bd55d72f8d85b5827cca6687e9c0fc27","src/iter.rs":"5e5e92e86a18e747f6687f4b3853aa2eaaa1121af43f3833b940f074baa32302","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":"501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"} \ No newline at end of file
diff --git a/vendor/generic-array-0.14.4/CHANGELOG.md b/vendor/generic-array-0.14.4/CHANGELOG.md
new file mode 100644
index 00000000..da20e891
--- /dev/null
+++ b/vendor/generic-array-0.14.4/CHANGELOG.md
@@ -0,0 +1,90 @@
+* **`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-0.14.4/Cargo.toml b/vendor/generic-array-0.14.4/Cargo.toml
new file mode 100644
index 00000000..e802b576
--- /dev/null
+++ b/vendor/generic-array-0.14.4/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.4"
+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-0.14.4/DESIGN.md b/vendor/generic-array-0.14.4/DESIGN.md
new file mode 100644
index 00000000..547bc7bd
--- /dev/null
+++ b/vendor/generic-array-0.14.4/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,
+{