Import generic-array 0.14.6 upstream upstream/0.14.6
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 22 Mar 2023 02:06:56 +0000 (11:06 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 22 Mar 2023 02:06:56 +0000 (11:06 +0900)
16 files changed:
.cargo_vcs_info.json [new file with mode: 0644]
CHANGELOG.md [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
Cargo.toml.orig [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README.md [new file with mode: 0644]
build.rs [new file with mode: 0644]
src/arr.rs [new file with mode: 0644]
src/functional.rs [new file with mode: 0644]
src/hex.rs [new file with mode: 0644]
src/impl_serde.rs [new file with mode: 0644]
src/impl_zeroize.rs [new file with mode: 0644]
src/impls.rs [new file with mode: 0644]
src/iter.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
src/sequence.rs [new file with mode: 0644]

diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644 (file)
index 0000000..1ccb5f8
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "bd2832933f655cd58b59a0e5a57dd6941a3d0322"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644 (file)
index 0000000..f7e0766
--- /dev/null
@@ -0,0 +1,98 @@
+* **`0.14.6`**\r
+    * Add an optional `Zeroize` impl for `GenericArray` (#126 and #112)\r
+    * Cleanup some unsafe (#125) and typos (#114)\r
+    * Use `include` in `Cargo.toml` to reduce package size\r
+\r
+* **`0.14.5`**\r
+    * Fix unsoundness behavior in `GenericArrayIter::clone` ([#120](https://github.com/fizyk20/generic-array/pull/120))\r
+\r
+* **`0.14.4`**\r
+    * Update `typenum` to `1.12.0`\r
+    * Make `Drop` a no-op when the inner type does not require `Drop` (using `core::mem::needs_drop`)\r
+\r
+* **`0.14.3`**\r
+    * Improve behavior of `GenericArray::from_exact_iter` to assume `ExactIterator`s can lie.\r
+    * Fix alignment of zero-length `GenericArray`s\r
+    * Implement `From<&[T; N]> for &GenericArray<T, N>` and its mutable variant\r
+\r
+* **`0.14.2`**\r
+    * Lower MSRV to `1.36.0` without `From<[T; N]>` implementations.\r
+\r
+* **`0.14.1`**\r
+    * Fix element conversions in `arr!` macro.\r
+\r
+* **`0.14.0`**\r
+    * Replace `Into` implementations with the more general `From`.\r
+        * Requires minumum Rust version of 1.41.0\r
+    * Fix unsoundness in `arr!` macro.\r
+    * Fix meta variable misuse\r
+    * Fix Undefined Behavior across the crate by switching to `MaybeUninit`\r
+    * Improve some documentation and doctests\r
+    * Add `AsRef<[T; N]>` and `AsMut<[T; N]>` impls to `GenericArray<T, N>`\r
+    * Add `Split` impl for `&GenericArray` and `&mut GenericArray`\r
+\r
+* **`0.13.2`**\r
+    * Add feature `more_lengths`, which adds more `From`/`Into` implementations for arrays of various lengths.\r
+\r
+* **`0.13.1`**\r
+    * Mark `GenericArray` as `#[repr(transparent)]`\r
+    * Implement `Into<[T; N]>` for `GenericArray<T, N>` up to N=32\r
+\r
+* **`0.13.0`**\r
+    * Allow `arr!` to be imported with use syntax.\r
+        * Requires minumum Rust version of 1.30.1\r
+\r
+* **`0.12.2`**\r
+    * Implement `FusedIterator` for `GenericArrayIter`\r
+\r
+* **`0.12.1`**\r
+    * Use internal iteration where possible and provide more efficient internal iteration methods.\r
+\r
+* **`0.12.0`**\r
+    * Allow trailing commas in `arr!` macro.\r
+    * **BREAKING**: Serialize `GenericArray` using `serde` tuples, instead of variable-length sequences. This may not be compatible with old serialized data.\r
+\r
+* **`0.11.0`**\r
+    * **BREAKING** Redesign `GenericSequence` with an emphasis on use in generic type parameters.\r
+    * Add `MappedGenericSequence` and `FunctionalSequence`\r
+        * Implements optimized `map`, `zip` and `fold` for `GenericArray`, `&GenericArray` and `&mut GenericArray`\r
+    * **BREAKING** Remove `map_ref`, `zip_ref` and `map_slice`\r
+        * `map_slice` is now equivalent to `GenericArray::from_iter(slice.iter().map(...))`\r
+* **`0.10.0`**\r
+    * Add `GenericSequence`, `Lengthen`, `Shorten`, `Split` and `Concat` traits.\r
+    * Redefine `transmute` to avert errors.\r
+* **`0.9.0`**\r
+    * Rewrite construction methods to be well-defined in panic situations, correctly dropping elements.\r
+    * `NoDrop` crate replaced by `ManuallyDrop` as it became stable in Rust core.\r
+    * Add optimized `map`/`map_ref` and `zip`/`zip_ref` methods to `GenericArray`\r
+* **`0.8.0`**\r
+    * Implement `AsRef`, `AsMut`, `Borrow`, `BorrowMut`, `Hash` for `GenericArray`\r
+    * Update `serde` to `1.0`\r
+    * Update `typenum`\r
+    * Make macro `arr!` non-cloning\r
+    * Implement `From<[T; N]>` up to `N=32`\r
+    * Fix #45\r
+* **`0.7.0`**\r
+    * Upgrade `serde` to `0.9`\r
+    * Make `serde` with `no_std`\r
+    * Implement `PartialOrd`/`Ord` for `GenericArray`\r
+* **`0.6.0`**\r
+    * Fixed #30\r
+    * Implement `Default` for `GenericArray`\r
+    * Implement `LowerHex` and `UpperHex` for `GenericArray<u8, N>`\r
+    * Use `precision` formatting field in hex representation\r
+    * Add `as_slice`, `as_mut_slice`\r
+    * Remove `GenericArray::new` in favor of `Default` trait\r
+    * Add `from_slice` and `from_mut_slice`\r
+    * `no_std` and `core` for crate.\r
+* **`0.5.0`**\r
+    * Update `serde`\r
+    * remove `no_std` feature, fixed #19\r
+* **`0.4.0`**\r
+    * Re-export `typenum`\r
+* **`0.3.0`**\r
+    * Implement `IntoIter` for `GenericArray`\r
+    * Add `map` method\r
+    * Add optional `serde` (de)serialization support feature.\r
+* **`< 0.3.0`**\r
+    * Initial implementation in late 2015\r
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..f04fc7b
--- /dev/null
@@ -0,0 +1,75 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+name = "generic-array"
+version = "0.14.6"
+authors = [
+    "Bartłomiej Kamiński <fizyk20@gmail.com>",
+    "Aaron Trent <novacrazy@gmail.com>",
+]
+include = [
+    "src/**/*",
+    "LICENSE",
+    "README.md",
+    "CHANGELOG.md",
+    "build.rs",
+]
+description = "Generic types implementing functionality of arrays"
+documentation = "http://fizyk20.github.io/generic-array/generic_array/"
+readme = "README.md"
+keywords = [
+    "generic",
+    "array",
+]
+categories = [
+    "data-structures",
+    "no-std",
+]
+license = "MIT"
+repository = "https://github.com/fizyk20/generic-array.git"
+
+[package.metadata.docs.rs]
+features = [
+    "serde",
+    "zeroize",
+]
+
+[lib]
+name = "generic_array"
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+default-features = false
+
+[dependencies.typenum]
+version = "1.12"
+
+[dependencies.zeroize]
+version = "1"
+optional = true
+default-features = false
+
+[dev-dependencies.bincode]
+version = "1.0"
+
+[dev-dependencies.serde_json]
+version = "1.0"
+
+[build-dependencies.version_check]
+version = "0.9"
+
+[features]
+more_lengths = []
+
+[badges.travis-ci]
+repository = "fizyk20/generic-array"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644 (file)
index 0000000..2a1596e
--- /dev/null
@@ -0,0 +1,43 @@
+[package]\r
+\r
+name = "generic-array"\r
+version = "0.14.6"\r
+authors = [ "Bartłomiej Kamiński <fizyk20@gmail.com>", "Aaron Trent <novacrazy@gmail.com>" ]\r
+\r
+description = "Generic types implementing functionality of arrays"\r
+readme = "README.md"\r
+\r
+license = "MIT"\r
+\r
+documentation = "http://fizyk20.github.io/generic-array/generic_array/"\r
+repository = "https://github.com/fizyk20/generic-array.git"\r
+\r
+keywords = ["generic", "array"]\r
+categories = ["data-structures", "no-std"]\r
+\r
+include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md", "build.rs"]\r
+\r
+[badges]\r
+travis-ci = { repository = "fizyk20/generic-array" }\r
+\r
+[lib]\r
+name = "generic_array"\r
+\r
+[features]\r
+more_lengths = []\r
+\r
+[dependencies]\r
+typenum = "1.12"\r
+serde = { version = "1.0", optional = true, default-features = false }\r
+zeroize = { version = "1", optional = true, default-features = false }\r
+\r
+[dev_dependencies]\r
+# this can't yet be made optional, see https://github.com/rust-lang/cargo/issues/1596\r
+serde_json = "1.0"\r
+bincode = "1.0"\r
+\r
+[build_dependencies]\r
+version_check = "0.9"\r
+\r
+[package.metadata.docs.rs]\r
+features = ["serde", "zeroize"]
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..6d31894
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)\r
+\r
+Copyright (c) 2015 Bartłomiej Kamiński\r
+\r
+Permission is hereby granted, free of charge, to any person obtaining a copy\r
+of this software and associated documentation files (the "Software"), to deal\r
+in the Software without restriction, including without limitation the rights\r
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+copies of the Software, and to permit persons to whom the Software is\r
+furnished to do so, subject to the following conditions:\r
+\r
+The above copyright notice and this permission notice shall be included in all\r
+copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..cf54f40
--- /dev/null
+++ b/README.md
@@ -0,0 +1,62 @@
+[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array)\r
+[![Build Status](https://travis-ci.org/fizyk20/generic-array.svg?branch=master)](https://travis-ci.org/fizyk20/generic-array)\r
+# generic-array\r
+\r
+This crate implements generic array types for Rust.\r
+\r
+**Requires minumum Rust version of 1.36.0, or 1.41.0 for `From<[T; N]>` implementations**\r
+\r
+[Documentation](http://fizyk20.github.io/generic-array/generic_array/)\r
+\r
+## Usage\r
+\r
+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:\r
+\r
+```rust\r
+struct Foo<N> {\r
+       data: [i32; N]\r
+}\r
+```\r
+\r
+**generic-array** defines a new trait `ArrayLength<T>` and a struct `GenericArray<T, N: ArrayLength<T>>`, which let the above be implemented as:\r
+\r
+```rust\r
+struct Foo<N: ArrayLength<i32>> {\r
+       data: GenericArray<i32, N>\r
+}\r
+```\r
+\r
+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:\r
+\r
+```rust\r
+use generic_array::typenum::U5;\r
+\r
+struct Foo<N: ArrayLength<i32>> {\r
+    data: GenericArray<i32, N>\r
+}\r
+\r
+fn main() {\r
+    let foo = Foo::<U5>{data: GenericArray::default()};\r
+}\r
+```\r
+\r
+For example, `GenericArray<T, U5>` would work almost like `[T; 5]`:\r
+\r
+```rust\r
+use generic_array::typenum::U5;\r
+\r
+struct Foo<T, N: ArrayLength<T>> {\r
+    data: GenericArray<T, N>\r
+}\r
+\r
+fn main() {\r
+    let foo = Foo::<i32, U5>{data: GenericArray::default()};\r
+}\r
+```\r
+\r
+In version 0.1.1 an `arr!` macro was introduced, allowing for creation of arrays as shown below:\r
+\r
+```rust\r
+let array = arr![u32; 1, 2, 3];\r
+assert_eq!(array[2], 3);\r
+```\r
diff --git a/build.rs b/build.rs
new file mode 100644 (file)
index 0000000..c27c7e3
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,5 @@
+fn main() {\r
+    if version_check::is_min_version("1.41.0").unwrap_or(false) {\r
+        println!("cargo:rustc-cfg=relaxed_coherence");\r
+    }\r
+}\r
diff --git a/src/arr.rs b/src/arr.rs
new file mode 100644 (file)
index 0000000..cdcc038
--- /dev/null
@@ -0,0 +1,125 @@
+//! Implementation for `arr!` macro.\r
+\r
+use super::ArrayLength;\r
+use core::ops::Add;\r
+use typenum::U1;\r
+\r
+/// Helper trait for `arr!` macro\r
+pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {\r
+    /// Resulting length\r
+    type Output: ArrayLength<T>;\r
+}\r
+\r
+impl<T, N1, N2> AddLength<T, N2> for N1\r
+where\r
+    N1: ArrayLength<T> + Add<N2>,\r
+    N2: ArrayLength<T>,\r
+    <N1 as Add<N2>>::Output: ArrayLength<T>,\r
+{\r
+    type Output = <N1 as Add<N2>>::Output;\r
+}\r
+\r
+/// Helper type for `arr!` macro\r
+pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;\r
+\r
+#[doc(hidden)]\r
+#[macro_export]\r
+macro_rules! arr_impl {\r
+    (@replace_expr $e:expr) => { 1 };\r
+    ($T:ty; $N:ty, [$($x:expr),*], []) => ({\r
+        const __ARR_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*;\r
+\r
+        #[inline(always)]\r
+        fn __do_transmute<T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {\r
+            unsafe { $crate::transmute(arr) }\r
+        }\r
+\r
+        let _: [(); <$N as $crate::typenum::Unsigned>::USIZE] = [(); __ARR_LENGTH];\r
+\r
+        __do_transmute::<$T, $N>([$($x as $T),*])\r
+    });\r
+    ($T:ty; $N:ty, [], [$x1:expr]) => (\r
+        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])\r
+    );\r
+    ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (\r
+        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])\r
+    );\r
+    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (\r
+        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])\r
+    );\r
+    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (\r
+        $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+])\r
+    );\r
+}\r
+\r
+/// Macro allowing for easy generation of Generic Arrays.\r
+/// Example: `let test = arr![u32; 1, 2, 3];`\r
+#[macro_export]\r
+macro_rules! arr {\r
+    ($T:ty; $(,)*) => ({\r
+        unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }\r
+    });\r
+    ($T:ty; $($x:expr),* $(,)*) => (\r
+        $crate::arr_impl!($T; $crate::typenum::U0, [], [$($x),*])\r
+    );\r
+    ($($x:expr,)+) => (arr![$($x),+]);\r
+    () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")\r
+}\r
+\r
+mod doctests_only {\r
+    ///\r
+    /// # With ellision\r
+    ///\r
+    /// Testing that lifetimes aren't transmuted when they're ellided.\r
+    ///\r
+    /// ```compile_fail\r
+    /// #[macro_use] extern crate generic_array;\r
+    /// fn main() {\r
+    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {\r
+    ///        arr![&A; a][0]\r
+    ///    }\r
+    /// }\r
+    /// ```\r
+    ///\r
+    /// ```rust\r
+    /// #[macro_use] extern crate generic_array;\r
+    /// fn main() {\r
+    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {\r
+    ///        arr![&A; a][0]\r
+    ///    }\r
+    /// }\r
+    /// ```\r
+    ///\r
+    /// # Without ellision\r
+    ///\r
+    /// Testing that lifetimes aren't transmuted when they're specified explicitly.\r
+    ///\r
+    /// ```compile_fail\r
+    /// #[macro_use] extern crate generic_array;\r
+    /// fn main() {\r
+    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {\r
+    ///        arr![&'a A; a][0]\r
+    ///    }\r
+    /// }\r
+    /// ```\r
+    ///\r
+    /// ```compile_fail\r
+    /// #[macro_use] extern crate generic_array;\r
+    /// fn main() {\r
+    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {\r
+    ///        arr![&'static A; a][0]\r
+    ///    }\r
+    /// }\r
+    /// ```\r
+    ///\r
+    /// ```rust\r
+    /// #[macro_use] extern crate generic_array;\r
+    /// fn main() {\r
+    ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {\r
+    ///        arr![&'a A; a][0]\r
+    ///    }\r
+    /// }\r
+    /// ```\r
+    #[allow(dead_code)]\r
+    pub enum DocTests {}\r
+}\r
diff --git a/src/functional.rs b/src/functional.rs
new file mode 100644 (file)
index 0000000..2ddcc5c
--- /dev/null
@@ -0,0 +1,95 @@
+//! Functional programming with generic sequences\r
+//!\r
+//! Please see `tests/generics.rs` for examples of how to best use these in your generic functions.\r
+\r
+use super::ArrayLength;\r
+use core::iter::FromIterator;\r
+\r
+use crate::sequence::*;\r
+\r
+/// Defines the relationship between one generic sequence and another,\r
+/// for operations such as `map` and `zip`.\r
+pub unsafe trait MappedGenericSequence<T, U>: GenericSequence<T>\r
+where\r
+    Self::Length: ArrayLength<U>,\r
+{\r
+    /// Mapped sequence type\r
+    type Mapped: GenericSequence<U, Length = Self::Length>;\r
+}\r
+\r
+unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a S\r
+where\r
+    &'a S: GenericSequence<T>,\r
+    S: GenericSequence<T, Length = <&'a S as GenericSequence<T>>::Length>,\r
+    <S as GenericSequence<T>>::Length: ArrayLength<U>,\r
+{\r
+    type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;\r
+}\r
+\r
+unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a mut S\r
+where\r
+    &'a mut S: GenericSequence<T>,\r
+    S: GenericSequence<T, Length = <&'a mut S as GenericSequence<T>>::Length>,\r
+    <S as GenericSequence<T>>::Length: ArrayLength<U>,\r
+{\r
+    type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;\r
+}\r
+\r
+/// Accessor type for a mapped generic sequence\r
+pub type MappedSequence<S, T, U> =\r
+    <<S as MappedGenericSequence<T, U>>::Mapped as GenericSequence<U>>::Sequence;\r
+\r
+/// Defines functional programming methods for generic sequences\r
+pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {\r
+    /// Maps a `GenericSequence` to another `GenericSequence`.\r
+    ///\r
+    /// If the mapping function panics, any already initialized elements in the new sequence\r
+    /// will be dropped, AND any unused elements in the source sequence will also be dropped.\r
+    fn map<U, F>(self, f: F) -> MappedSequence<Self, T, U>\r
+    where\r
+        Self: MappedGenericSequence<T, U>,\r
+        Self::Length: ArrayLength<U>,\r
+        F: FnMut(Self::Item) -> U,\r
+    {\r
+        FromIterator::from_iter(self.into_iter().map(f))\r
+    }\r
+\r
+    /// Combines two `GenericSequence` instances and iterates through both of them,\r
+    /// initializing a new `GenericSequence` with the result of the zipped mapping function.\r
+    ///\r
+    /// If the mapping function panics, any already initialized elements in the new sequence\r
+    /// will be dropped, AND any unused elements in the source sequences will also be dropped.\r
+    #[inline]\r
+    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>\r
+    where\r
+        Self: MappedGenericSequence<T, U>,\r
+        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,\r
+        Self::Length: ArrayLength<B> + ArrayLength<U>,\r
+        Rhs: GenericSequence<B, Length = Self::Length>,\r
+        F: FnMut(Self::Item, Rhs::Item) -> U,\r
+    {\r
+        rhs.inverted_zip2(self, f)\r
+    }\r
+\r
+    /// Folds (or reduces) a sequence of data into a single value.\r
+    ///\r
+    /// If the fold function panics, any unused elements will be dropped.\r
+    fn fold<U, F>(self, init: U, f: F) -> U\r
+    where\r
+        F: FnMut(U, Self::Item) -> U,\r
+    {\r
+        self.into_iter().fold(init, f)\r
+    }\r
+}\r
+\r
+unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a S\r
+where\r
+    &'a S: GenericSequence<T>,\r
+{\r
+}\r
+\r
+unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a mut S\r
+where\r
+    &'a mut S: GenericSequence<T>,\r
+{\r
+}\r
diff --git a/src/hex.rs b/src/hex.rs
new file mode 100644 (file)
index 0000000..33c796f
--- /dev/null
@@ -0,0 +1,105 @@
+//! Generic array are commonly used as a return value for hash digests, so\r
+//! it's a good idea to allow to hexlify them easily. This module implements\r
+//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.\r
+//!\r
+//! Example:\r
+//!\r
+//! ```rust\r
+//! # #[macro_use]\r
+//! # extern crate generic_array;\r
+//! # extern crate typenum;\r
+//! # fn main() {\r
+//! let array = arr![u8; 10, 20, 30];\r
+//! assert_eq!(format!("{:x}", array), "0a141e");\r
+//! # }\r
+//! ```\r
+//!\r
+\r
+use core::{fmt, str, ops::Add, cmp::min};\r
+\r
+use typenum::*;\r
+\r
+use crate::{ArrayLength, GenericArray};\r
+\r
+static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";\r
+static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";\r
+\r
+impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>\r
+where\r
+    T: Add<T>,\r
+    <T as Add<T>>::Output: ArrayLength<u8>,\r
+{\r
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r
+        let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);\r
+        let max_hex = (max_digits >> 1) + (max_digits & 1);\r
+\r
+        if T::USIZE < 1024 {\r
+            // For small arrays use a stack allocated\r
+            // buffer of 2x number of bytes\r
+            let mut res = GenericArray::<u8, Sum<T, T>>::default();\r
+\r
+            self.iter().take(max_hex).enumerate().for_each(|(i, c)| {\r
+                res[i * 2] = LOWER_CHARS[(c >> 4) as usize];\r
+                res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];\r
+            });\r
+\r
+            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;\r
+        } else {\r
+            // For large array use chunks of up to 1024 bytes (2048 hex chars)\r
+            let mut buf = [0u8; 2048];\r
+            let mut digits_left = max_digits;\r
+\r
+            for chunk in self[..max_hex].chunks(1024) {\r
+                chunk.iter().enumerate().for_each(|(i, c)| {\r
+                    buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];\r
+                    buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];\r
+                });\r
+\r
+                let n = min(chunk.len() * 2, digits_left);\r
+                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;\r
+                digits_left -= n;\r
+            }\r
+        }\r
+        Ok(())\r
+    }\r
+}\r
+\r
+impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>\r
+where\r
+    T: Add<T>,\r
+    <T as Add<T>>::Output: ArrayLength<u8>,\r
+{\r
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r
+        let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);\r
+        let max_hex = (max_digits >> 1) + (max_digits & 1);\r
+\r
+        if T::USIZE < 1024 {\r
+            // For small arrays use a stack allocated\r
+            // buffer of 2x number of bytes\r
+            let mut res = GenericArray::<u8, Sum<T, T>>::default();\r
+\r
+            self.iter().take(max_hex).enumerate().for_each(|(i, c)| {\r
+                res[i * 2] = UPPER_CHARS[(c >> 4) as usize];\r
+                res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];\r
+            });\r
+\r
+            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;\r
+        } else {\r
+            // For large array use chunks of up to 1024 bytes (2048 hex chars)\r
+            let mut buf = [0u8; 2048];\r
+            let mut digits_left = max_digits;\r
+\r
+            for chunk in self[..max_hex].chunks(1024) {\r
+                chunk.iter().enumerate().for_each(|(i, c)| {\r
+                    buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];\r
+                    buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];\r
+                });\r
+\r
+                let n = min(chunk.len() * 2, digits_left);\r
+                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;\r
+                digits_left -= n;\r
+            }\r
+        }\r
+        Ok(())\r
+    }\r
+}\r
diff --git a/src/impl_serde.rs b/src/impl_serde.rs
new file mode 100644 (file)
index 0000000..49c095a
--- /dev/null
@@ -0,0 +1,108 @@
+//! Serde serialization/deserialization implementation\r
+\r
+use core::fmt;\r
+use core::marker::PhantomData;\r
+use serde::de::{self, SeqAccess, Visitor};\r
+use serde::{ser::SerializeTuple, Deserialize, Deserializer, Serialize, Serializer};\r
+use {ArrayLength, GenericArray};\r
+\r
+impl<T, N> Serialize for GenericArray<T, N>\r
+where\r
+    T: Serialize,\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline]\r
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\r
+    where\r
+        S: Serializer,\r
+    {\r
+        let mut tup = serializer.serialize_tuple(N::USIZE)?;\r
+        for el in self {\r
+            tup.serialize_element(el)?;\r
+        }\r
+\r
+        tup.end()\r
+    }\r
+}\r
+\r
+struct GAVisitor<T, N> {\r
+    _t: PhantomData<T>,\r
+    _n: PhantomData<N>,\r
+}\r
+\r
+impl<'de, T, N> Visitor<'de> for GAVisitor<T, N>\r
+where\r
+    T: Deserialize<'de> + Default,\r
+    N: ArrayLength<T>,\r
+{\r
+    type Value = GenericArray<T, N>;\r
+\r
+    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\r
+        formatter.write_str("struct GenericArray")\r
+    }\r
+\r
+    fn visit_seq<A>(self, mut seq: A) -> Result<GenericArray<T, N>, A::Error>\r
+    where\r
+        A: SeqAccess<'de>,\r
+    {\r
+        let mut result = GenericArray::default();\r
+        for i in 0..N::USIZE {\r
+            result[i] = seq\r
+                .next_element()?\r
+                .ok_or_else(|| de::Error::invalid_length(i, &self))?;\r
+        }\r
+        Ok(result)\r
+    }\r
+}\r
+\r
+impl<'de, T, N> Deserialize<'de> for GenericArray<T, N>\r
+where\r
+    T: Deserialize<'de> + Default,\r
+    N: ArrayLength<T>,\r
+{\r
+    fn deserialize<D>(deserializer: D) -> Result<GenericArray<T, N>, D::Error>\r
+    where\r
+        D: Deserializer<'de>,\r
+    {\r
+        let visitor = GAVisitor {\r
+            _t: PhantomData,\r
+            _n: PhantomData,\r
+        };\r
+        deserializer.deserialize_tuple(N::USIZE, visitor)\r
+    }\r
+}\r
+\r
+#[cfg(test)]\r
+mod tests {\r
+    use super::*;\r
+    use bincode;\r
+    use typenum;\r
+\r
+    #[test]\r
+    fn test_serialize() {\r
+        let array = GenericArray::<u8, typenum::U2>::default();\r
+        let serialized = bincode::serialize(&array);\r
+        assert!(serialized.is_ok());\r
+    }\r
+\r
+    #[test]\r
+    fn test_deserialize() {\r
+        let mut array = GenericArray::<u8, typenum::U2>::default();\r
+        array[0] = 1;\r
+        array[1] = 2;\r
+        let serialized = bincode::serialize(&array).unwrap();\r
+        let deserialized = bincode::deserialize::<GenericArray<u8, typenum::U2>>(&serialized);\r
+        assert!(deserialized.is_ok());\r
+        let array = deserialized.unwrap();\r
+        assert_eq!(array[0], 1);\r
+        assert_eq!(array[1], 2);\r
+    }\r
+\r
+    #[test]\r
+    fn test_serialized_size() {\r
+        let array = GenericArray::<u8, typenum::U1>::default();\r
+        let size = bincode::serialized_size(&array).unwrap();\r
+        assert_eq!(size, 1);\r
+    }\r
+\r
+}\r
diff --git a/src/impl_zeroize.rs b/src/impl_zeroize.rs
new file mode 100644 (file)
index 0000000..9937e4b
--- /dev/null
@@ -0,0 +1,25 @@
+use {ArrayLength, GenericArray};\r
+\r
+use zeroize::Zeroize;\r
+\r
+#[cfg_attr(docsrs, doc(cfg(feature = "zeroize")))]\r
+impl<T: Zeroize, N: ArrayLength<T>> Zeroize for GenericArray<T, N> {\r
+    fn zeroize(&mut self) {\r
+        self.as_mut_slice().iter_mut().zeroize()\r
+    }\r
+}\r
+\r
+#[cfg(test)]\r
+mod tests {\r
+    use super::*;\r
+\r
+    #[test]\r
+    fn test_zeroize() {\r
+        let mut array = GenericArray::<u8, typenum::U2>::default();\r
+        array[0] = 4;\r
+        array[1] = 9;\r
+        array.zeroize();\r
+        assert_eq!(array[0], 0);\r
+        assert_eq!(array[1], 0);\r
+    }\r
+}
\ No newline at end of file
diff --git a/src/impls.rs b/src/impls.rs
new file mode 100644 (file)
index 0000000..47ecc1d
--- /dev/null
@@ -0,0 +1,269 @@
+use core::borrow::{Borrow, BorrowMut};\r
+use core::cmp::Ordering;\r
+use core::fmt::{self, Debug};\r
+use core::hash::{Hash, Hasher};\r
+\r
+use super::{ArrayLength, GenericArray};\r
+\r
+use crate::functional::*;\r
+use crate::sequence::*;\r
+\r
+impl<T: Default, N> Default for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline(always)]\r
+    fn default() -> Self {\r
+        Self::generate(|_| T::default())\r
+    }\r
+}\r
+\r
+impl<T: Clone, N> Clone for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn clone(&self) -> GenericArray<T, N> {\r
+        self.map(Clone::clone)\r
+    }\r
+}\r
+\r
+impl<T: Copy, N> Copy for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+    N::ArrayType: Copy,\r
+{\r
+}\r
+\r
+impl<T: PartialEq, N> PartialEq for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn eq(&self, other: &Self) -> bool {\r
+        **self == **other\r
+    }\r
+}\r
+impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}\r
+\r
+impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {\r
+        PartialOrd::partial_cmp(self.as_slice(), other.as_slice())\r
+    }\r
+}\r
+\r
+impl<T: Ord, N> Ord for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {\r
+        Ord::cmp(self.as_slice(), other.as_slice())\r
+    }\r
+}\r
+\r
+impl<T: Debug, N> Debug for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {\r
+        self[..].fmt(fmt)\r
+    }\r
+}\r
+\r
+impl<T, N> Borrow<[T]> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline(always)]\r
+    fn borrow(&self) -> &[T] {\r
+        &self[..]\r
+    }\r
+}\r
+\r
+impl<T, N> BorrowMut<[T]> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline(always)]\r
+    fn borrow_mut(&mut self) -> &mut [T] {\r
+        &mut self[..]\r
+    }\r
+}\r
+\r
+impl<T, N> AsRef<[T]> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline(always)]\r
+    fn as_ref(&self) -> &[T] {\r
+        &self[..]\r
+    }\r
+}\r
+\r
+impl<T, N> AsMut<[T]> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline(always)]\r
+    fn as_mut(&mut self) -> &mut [T] {\r
+        &mut self[..]\r
+    }\r
+}\r
+\r
+impl<T: Hash, N> Hash for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn hash<H>(&self, state: &mut H)\r
+    where\r
+        H: Hasher,\r
+    {\r
+        Hash::hash(&self[..], state)\r
+    }\r
+}\r
+\r
+macro_rules! impl_from {\r
+    ($($n: expr => $ty: ty),*) => {\r
+        $(\r
+            impl<T> From<[T; $n]> for GenericArray<T, $ty> {\r
+                #[inline(always)]\r
+                fn from(arr: [T; $n]) -> Self {\r
+                    unsafe { $crate::transmute(arr) }\r
+                }\r
+            }\r
+\r
+            #[cfg(relaxed_coherence)]\r
+            impl<T> From<GenericArray<T, $ty>> for [T; $n] {\r
+                #[inline(always)]\r
+                fn from(sel: GenericArray<T, $ty>) -> [T; $n] {\r
+                    unsafe { $crate::transmute(sel) }\r
+                }\r
+            }\r
+\r
+            impl<'a, T> From<&'a [T; $n]> for &'a GenericArray<T, $ty> {\r
+                #[inline]\r
+                fn from(slice: &[T; $n]) -> &GenericArray<T, $ty> {\r
+                    unsafe { &*(slice.as_ptr() as *const GenericArray<T, $ty>) }\r
+                }\r
+            }\r
+\r
+            impl<'a, T> From<&'a mut [T; $n]> for &'a mut GenericArray<T, $ty> {\r
+                #[inline]\r
+                fn from(slice: &mut [T; $n]) -> &mut GenericArray<T, $ty> {\r
+                    unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, $ty>) }\r
+                }\r
+            }\r
+\r
+            #[cfg(not(relaxed_coherence))]\r
+            impl<T> Into<[T; $n]> for GenericArray<T, $ty> {\r
+                #[inline(always)]\r
+                fn into(self) -> [T; $n] {\r
+                    unsafe { $crate::transmute(self) }\r
+                }\r
+            }\r
+\r
+            impl<T> AsRef<[T; $n]> for GenericArray<T, $ty> {\r
+                #[inline]\r
+                fn as_ref(&self) -> &[T; $n] {\r
+                    unsafe { $crate::transmute(self) }\r
+                }\r
+            }\r
+\r
+            impl<T> AsMut<[T; $n]> for GenericArray<T, $ty> {\r
+                #[inline]\r
+                fn as_mut(&mut self) -> &mut [T; $n] {\r
+                    unsafe { $crate::transmute(self) }\r
+                }\r
+            }\r
+        )*\r
+    }\r
+}\r
+\r
+impl_from! {\r
+    1  => ::typenum::U1,\r
+    2  => ::typenum::U2,\r
+    3  => ::typenum::U3,\r
+    4  => ::typenum::U4,\r
+    5  => ::typenum::U5,\r
+    6  => ::typenum::U6,\r
+    7  => ::typenum::U7,\r
+    8  => ::typenum::U8,\r
+    9  => ::typenum::U9,\r
+    10 => ::typenum::U10,\r
+    11 => ::typenum::U11,\r
+    12 => ::typenum::U12,\r
+    13 => ::typenum::U13,\r
+    14 => ::typenum::U14,\r
+    15 => ::typenum::U15,\r
+    16 => ::typenum::U16,\r
+    17 => ::typenum::U17,\r
+    18 => ::typenum::U18,\r
+    19 => ::typenum::U19,\r
+    20 => ::typenum::U20,\r
+    21 => ::typenum::U21,\r
+    22 => ::typenum::U22,\r
+    23 => ::typenum::U23,\r
+    24 => ::typenum::U24,\r
+    25 => ::typenum::U25,\r
+    26 => ::typenum::U26,\r
+    27 => ::typenum::U27,\r
+    28 => ::typenum::U28,\r
+    29 => ::typenum::U29,\r
+    30 => ::typenum::U30,\r
+    31 => ::typenum::U31,\r
+    32 => ::typenum::U32\r
+}\r
+\r
+#[cfg(feature = "more_lengths")]\r
+impl_from! {\r
+    33 => ::typenum::U33,\r
+    34 => ::typenum::U34,\r
+    35 => ::typenum::U35,\r
+    36 => ::typenum::U36,\r
+    37 => ::typenum::U37,\r
+    38 => ::typenum::U38,\r
+    39 => ::typenum::U39,\r
+    40 => ::typenum::U40,\r
+    41 => ::typenum::U41,\r
+    42 => ::typenum::U42,\r
+    43 => ::typenum::U43,\r
+    44 => ::typenum::U44,\r
+    45 => ::typenum::U45,\r
+    46 => ::typenum::U46,\r
+    47 => ::typenum::U47,\r
+    48 => ::typenum::U48,\r
+    49 => ::typenum::U49,\r
+    50 => ::typenum::U50,\r
+    51 => ::typenum::U51,\r
+    52 => ::typenum::U52,\r
+    53 => ::typenum::U53,\r
+    54 => ::typenum::U54,\r
+    55 => ::typenum::U55,\r
+    56 => ::typenum::U56,\r
+    57 => ::typenum::U57,\r
+    58 => ::typenum::U58,\r
+    59 => ::typenum::U59,\r
+    60 => ::typenum::U60,\r
+    61 => ::typenum::U61,\r
+    62 => ::typenum::U62,\r
+    63 => ::typenum::U63,\r
+    64 => ::typenum::U64,\r
+\r
+    70 => ::typenum::U70,\r
+    80 => ::typenum::U80,\r
+    90 => ::typenum::U90,\r
+\r
+    100 => ::typenum::U100,\r
+    200 => ::typenum::U200,\r
+    300 => ::typenum::U300,\r
+    400 => ::typenum::U400,\r
+    500 => ::typenum::U500,\r
+\r
+    128 => ::typenum::U128,\r
+    256 => ::typenum::U256,\r
+    512 => ::typenum::U512,\r
+\r
+    1000 => ::typenum::U1000,\r
+    1024 => ::typenum::U1024\r
+}\r
diff --git a/src/iter.rs b/src/iter.rs
new file mode 100644 (file)
index 0000000..784ffa9
--- /dev/null
@@ -0,0 +1,251 @@
+//! `GenericArray` iterator implementation.\r
+\r
+use super::{ArrayLength, GenericArray};\r
+use core::iter::FusedIterator;\r
+use core::mem::ManuallyDrop;\r
+use core::{cmp, fmt, mem, ptr};\r
+\r
+/// An iterator that moves out of a `GenericArray`\r
+pub struct GenericArrayIter<T, N: ArrayLength<T>> {\r
+    // Invariants: index <= index_back <= N\r
+    // Only values in array[index..index_back] are alive at any given time.\r
+    // Values from array[..index] and array[index_back..] are already moved/dropped.\r
+    array: ManuallyDrop<GenericArray<T, N>>,\r
+    index: usize,\r
+    index_back: usize,\r
+}\r
+\r
+#[cfg(test)]\r
+mod test {\r
+    use super::*;\r
+\r
+    fn send<I: Send>(_iter: I) {}\r
+\r
+    #[test]\r
+    fn test_send_iter() {\r
+        send(GenericArray::from([1, 2, 3, 4]).into_iter());\r
+    }\r
+}\r
+\r
+impl<T, N> GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    /// Returns the remaining items of this iterator as a slice\r
+    #[inline]\r
+    pub fn as_slice(&self) -> &[T] {\r
+        &self.array.as_slice()[self.index..self.index_back]\r
+    }\r
+\r
+    /// Returns the remaining items of this iterator as a mutable slice\r
+    #[inline]\r
+    pub fn as_mut_slice(&mut self) -> &mut [T] {\r
+        &mut self.array.as_mut_slice()[self.index..self.index_back]\r
+    }\r
+}\r
+\r
+impl<T, N> IntoIterator for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    type Item = T;\r
+    type IntoIter = GenericArrayIter<T, N>;\r
+\r
+    fn into_iter(self) -> Self::IntoIter {\r
+        GenericArrayIter {\r
+            array: ManuallyDrop::new(self),\r
+            index: 0,\r
+            index_back: N::USIZE,\r
+        }\r
+    }\r
+}\r
+\r
+// Based on work in rust-lang/rust#49000\r
+impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\r
+        f.debug_tuple("GenericArrayIter")\r
+            .field(&self.as_slice())\r
+            .finish()\r
+    }\r
+}\r
+\r
+impl<T, N> Drop for GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline]\r
+    fn drop(&mut self) {\r
+        if mem::needs_drop::<T>() {\r
+            // Drop values that are still alive.\r
+            for p in self.as_mut_slice() {\r
+                unsafe {\r
+                    ptr::drop_in_place(p);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+// Based on work in rust-lang/rust#49000\r
+impl<T: Clone, N> Clone for GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn clone(&self) -> Self {\r
+        // This places all cloned elements at the start of the new array iterator,\r
+        // not at their original indices.\r
+\r
+        let mut array = unsafe { ptr::read(&self.array) };\r
+        let mut index_back = 0;\r
+\r
+        for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {\r
+            unsafe { ptr::write(dst, src.clone()) };\r
+            index_back += 1;\r
+        }\r
+\r
+        GenericArrayIter {\r
+            array,\r
+            index: 0,\r
+            index_back,\r
+        }\r
+    }\r
+}\r
+\r
+impl<T, N> Iterator for GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    type Item = T;\r
+\r
+    #[inline]\r
+    fn next(&mut self) -> Option<T> {\r
+        if self.index < self.index_back {\r
+            let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };\r
+\r
+            self.index += 1;\r
+\r
+            p\r
+        } else {\r
+            None\r
+        }\r
+    }\r
+\r
+    fn fold<B, F>(mut self, init: B, mut f: F) -> B\r
+    where\r
+        F: FnMut(B, Self::Item) -> B,\r
+    {\r
+        let ret = unsafe {\r
+            let GenericArrayIter {\r
+                ref array,\r
+                ref mut index,\r
+                index_back,\r
+            } = self;\r
+\r
+            let remaining = &array[*index..index_back];\r
+\r
+            remaining.iter().fold(init, |acc, src| {\r
+                let value = ptr::read(src);\r
+\r
+                *index += 1;\r
+\r
+                f(acc, value)\r
+            })\r
+        };\r
+\r
+        // ensure the drop happens here after iteration\r
+        drop(self);\r
+\r
+        ret\r
+    }\r
+\r
+    #[inline]\r
+    fn size_hint(&self) -> (usize, Option<usize>) {\r
+        let len = self.len();\r
+        (len, Some(len))\r
+    }\r
+\r
+    #[inline]\r
+    fn count(self) -> usize {\r
+        self.len()\r
+    }\r
+\r
+    fn nth(&mut self, n: usize) -> Option<T> {\r
+        // First consume values prior to the nth.\r
+        let ndrop = cmp::min(n, self.len());\r
+\r
+        for p in &mut self.array[self.index..self.index + ndrop] {\r
+            self.index += 1;\r
+\r
+            unsafe {\r
+                ptr::drop_in_place(p);\r
+            }\r
+        }\r
+\r
+        self.next()\r
+    }\r
+\r
+    #[inline]\r
+    fn last(mut self) -> Option<T> {\r
+        // Note, everything else will correctly drop first as `self` leaves scope.\r
+        self.next_back()\r
+    }\r
+}\r
+\r
+impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn next_back(&mut self) -> Option<T> {\r
+        if self.index < self.index_back {\r
+            self.index_back -= 1;\r
+\r
+            unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }\r
+        } else {\r
+            None\r
+        }\r
+    }\r
+\r
+    fn rfold<B, F>(mut self, init: B, mut f: F) -> B\r
+    where\r
+        F: FnMut(B, Self::Item) -> B,\r
+    {\r
+        let ret = unsafe {\r
+            let GenericArrayIter {\r
+                ref array,\r
+                index,\r
+                ref mut index_back,\r
+            } = self;\r
+\r
+            let remaining = &array[index..*index_back];\r
+\r
+            remaining.iter().rfold(init, |acc, src| {\r
+                let value = ptr::read(src);\r
+\r
+                *index_back -= 1;\r
+\r
+                f(acc, value)\r
+            })\r
+        };\r
+\r
+        // ensure the drop happens here after iteration\r
+        drop(self);\r
+\r
+        ret\r
+    }\r
+}\r
+\r
+impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn len(&self) -> usize {\r
+        self.index_back - self.index\r
+    }\r
+}\r
+\r
+impl<T, N> FusedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {}\r
+\r
+// TODO: Implement `TrustedLen` when stabilized\r
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..43ab26f
--- /dev/null
@@ -0,0 +1,679 @@
+//! This crate implements a structure that can be used as a generic array type.\r
+//! Core Rust array types `[T; N]` can't be used generically with\r
+//! respect to `N`, so for example this:\r
+//!\r
+//! ```rust{compile_fail}\r
+//! struct Foo<T, N> {\r
+//!     data: [T; N]\r
+//! }\r
+//! ```\r
+//!\r
+//! won't work.\r
+//!\r
+//! **generic-array** exports a `GenericArray<T,N>` type, which lets\r
+//! the above be implemented as:\r
+//!\r
+//! ```rust\r
+//! use generic_array::{ArrayLength, GenericArray};\r
+//!\r
+//! struct Foo<T, N: ArrayLength<T>> {\r
+//!     data: GenericArray<T,N>\r
+//! }\r
+//! ```\r
+//!\r
+//! The `ArrayLength<T>` trait is implemented by default for\r
+//! [unsigned integer types](../typenum/uint/index.html) from\r
+//! [typenum](../typenum/index.html):\r
+//!\r
+//! ```rust\r
+//! # use generic_array::{ArrayLength, GenericArray};\r
+//! use generic_array::typenum::U5;\r
+//!\r
+//! struct Foo<N: ArrayLength<i32>> {\r
+//!     data: GenericArray<i32, N>\r
+//! }\r
+//!\r
+//! # fn main() {\r
+//! let foo = Foo::<U5>{data: GenericArray::default()};\r
+//! # }\r
+//! ```\r
+//!\r
+//! For example, `GenericArray<T, U5>` would work almost like `[T; 5]`:\r
+//!\r
+//! ```rust\r
+//! # use generic_array::{ArrayLength, GenericArray};\r
+//! use generic_array::typenum::U5;\r
+//!\r
+//! struct Foo<T, N: ArrayLength<T>> {\r
+//!     data: GenericArray<T, N>\r
+//! }\r
+//!\r
+//! # fn main() {\r
+//! let foo = Foo::<i32, U5>{data: GenericArray::default()};\r
+//! # }\r
+//! ```\r
+//!\r
+//! For ease of use, an `arr!` macro is provided - example below:\r
+//!\r
+//! ```\r
+//! # #[macro_use]\r
+//! # extern crate generic_array;\r
+//! # extern crate typenum;\r
+//! # fn main() {\r
+//! let array = arr![u32; 1, 2, 3];\r
+//! assert_eq!(array[2], 3);\r
+//! # }\r
+//! ```\r
+\r
+#![deny(missing_docs)]\r
+#![deny(meta_variable_misuse)]\r
+#![no_std]\r
+\r
+#[cfg(feature = "serde")]\r
+extern crate serde;\r
+\r
+#[cfg(feature = "zeroize")]\r
+extern crate zeroize;\r
+\r
+#[cfg(test)]\r
+extern crate bincode;\r
+\r
+pub extern crate typenum;\r
+\r
+mod hex;\r
+mod impls;\r
+\r
+#[cfg(feature = "serde")]\r
+mod impl_serde;\r
+\r
+#[cfg(feature = "zeroize")]\r
+mod impl_zeroize;\r
+\r
+use core::iter::FromIterator;\r
+use core::marker::PhantomData;\r
+use core::mem::{MaybeUninit, ManuallyDrop};\r
+use core::ops::{Deref, DerefMut};\r
+use core::{mem, ptr, slice};\r
+use typenum::bit::{B0, B1};\r
+use typenum::uint::{UInt, UTerm, Unsigned};\r
+\r
+#[cfg_attr(test, macro_use)]\r
+pub mod arr;\r
+pub mod functional;\r
+pub mod iter;\r
+pub mod sequence;\r
+\r
+use self::functional::*;\r
+pub use self::iter::GenericArrayIter;\r
+use self::sequence::*;\r
+\r
+/// Trait making `GenericArray` work, marking types to be used as length of an array\r
+pub unsafe trait ArrayLength<T>: Unsigned {\r
+    /// Associated type representing the array type for the number\r
+    type ArrayType;\r
+}\r
+\r
+unsafe impl<T> ArrayLength<T> for UTerm {\r
+    #[doc(hidden)]\r
+    type ArrayType = [T; 0];\r
+}\r
+\r
+/// Internal type used to generate a struct of appropriate size\r
+#[allow(dead_code)]\r
+#[repr(C)]\r
+#[doc(hidden)]\r
+pub struct GenericArrayImplEven<T, U> {\r
+    parent1: U,\r
+    parent2: U,\r
+    _marker: PhantomData<T>,\r
+}\r
+\r
+impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {\r
+    fn clone(&self) -> GenericArrayImplEven<T, U> {\r
+        GenericArrayImplEven {\r
+            parent1: self.parent1.clone(),\r
+            parent2: self.parent2.clone(),\r
+            _marker: PhantomData,\r
+        }\r
+    }\r
+}\r
+\r
+impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}\r
+\r
+/// Internal type used to generate a struct of appropriate size\r
+#[allow(dead_code)]\r
+#[repr(C)]\r
+#[doc(hidden)]\r
+pub struct GenericArrayImplOdd<T, U> {\r
+    parent1: U,\r
+    parent2: U,\r
+    data: T,\r
+}\r
+\r
+impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {\r
+    fn clone(&self) -> GenericArrayImplOdd<T, U> {\r
+        GenericArrayImplOdd {\r
+            parent1: self.parent1.clone(),\r
+            parent2: self.parent2.clone(),\r
+            data: self.data.clone(),\r
+        }\r
+    }\r
+}\r
+\r
+impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}\r
+\r
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {\r
+    #[doc(hidden)]\r
+    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;\r
+}\r
+\r
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {\r
+    #[doc(hidden)]\r
+    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;\r
+}\r
+\r
+/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]\r
+#[allow(dead_code)]\r
+#[repr(transparent)]\r
+pub struct GenericArray<T, U: ArrayLength<T>> {\r
+    data: U::ArrayType,\r
+}\r
+\r
+unsafe impl<T: Send, N: ArrayLength<T>> Send for GenericArray<T, N> {}\r
+unsafe impl<T: Sync, N: ArrayLength<T>> Sync for GenericArray<T, N> {}\r
+\r
+impl<T, N> Deref for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    type Target = [T];\r
+\r
+    #[inline(always)]\r
+    fn deref(&self) -> &[T] {\r
+        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::USIZE) }\r
+    }\r
+}\r
+\r
+impl<T, N> DerefMut for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    #[inline(always)]\r
+    fn deref_mut(&mut self) -> &mut [T] {\r
+        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::USIZE) }\r
+    }\r
+}\r
+\r
+/// Creates an array one element at a time using a mutable iterator\r
+/// you can write to with `ptr::write`.\r
+///\r
+/// Increment the position while iterating to mark off created elements,\r
+/// which will be dropped if `into_inner` is not called.\r
+#[doc(hidden)]\r
+pub struct ArrayBuilder<T, N: ArrayLength<T>> {\r
+    array: MaybeUninit<GenericArray<T, N>>,\r
+    position: usize,\r
+}\r
+\r
+impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {\r
+    #[doc(hidden)]\r
+    #[inline]\r
+    pub unsafe fn new() -> ArrayBuilder<T, N> {\r
+        ArrayBuilder {\r
+            array: MaybeUninit::uninit(),\r
+            position: 0,\r
+        }\r
+    }\r
+\r
+    /// Creates a mutable iterator for writing to the array using `ptr::write`.\r
+    ///\r
+    /// Increment the position value given as a mutable reference as you iterate\r
+    /// to mark how many elements have been created.\r
+    #[doc(hidden)]\r
+    #[inline]\r
+    pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {\r
+        ((&mut *self.array.as_mut_ptr()).iter_mut(), &mut self.position)\r
+    }\r
+\r
+    /// When done writing (assuming all elements have been written to),\r
+    /// get the inner array.\r
+    #[doc(hidden)]\r
+    #[inline]\r
+    pub unsafe fn into_inner(self) -> GenericArray<T, N> {\r
+        let array = ptr::read(&self.array);\r
+\r
+        mem::forget(self);\r
+\r
+        array.assume_init()\r
+    }\r
+}\r
+\r
+impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {\r
+    fn drop(&mut self) {\r
+        if mem::needs_drop::<T>() {\r
+            unsafe {\r
+                for value in &mut (&mut *self.array.as_mut_ptr())[..self.position] {\r
+                    ptr::drop_in_place(value);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+/// Consumes an array.\r
+///\r
+/// Increment the position while iterating and any leftover elements\r
+/// will be dropped if position does not go to N\r
+#[doc(hidden)]\r
+pub struct ArrayConsumer<T, N: ArrayLength<T>> {\r
+    array: ManuallyDrop<GenericArray<T, N>>,\r
+    position: usize,\r
+}\r
+\r
+impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {\r
+    #[doc(hidden)]\r
+    #[inline]\r
+    pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {\r
+        ArrayConsumer {\r
+            array: ManuallyDrop::new(array),\r
+            position: 0,\r
+        }\r
+    }\r
+\r
+    /// Creates an iterator and mutable reference to the internal position\r
+    /// to keep track of consumed elements.\r
+    ///\r
+    /// Increment the position as you iterate to mark off consumed elements\r
+    #[doc(hidden)]\r
+    #[inline]\r
+    pub unsafe fn iter_position(&mut self) -> (slice::Iter<T>, &mut usize) {\r
+        (self.array.iter(), &mut self.position)\r
+    }\r
+}\r
+\r
+impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {\r
+    fn drop(&mut self) {\r
+        if mem::needs_drop::<T>() {\r
+            for value in &mut self.array[self.position..N::USIZE] {\r
+                unsafe {\r
+                    ptr::drop_in_place(value);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+impl<'a, T: 'a, N> IntoIterator for &'a GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    type IntoIter = slice::Iter<'a, T>;\r
+    type Item = &'a T;\r
+\r
+    fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {\r
+        self.as_slice().iter()\r
+    }\r
+}\r
+\r
+impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    type IntoIter = slice::IterMut<'a, T>;\r
+    type Item = &'a mut T;\r
+\r
+    fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {\r
+        self.as_mut_slice().iter_mut()\r
+    }\r
+}\r
+\r
+impl<T, N> FromIterator<T> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    fn from_iter<I>(iter: I) -> GenericArray<T, N>\r
+    where\r
+        I: IntoIterator<Item = T>,\r
+    {\r
+        unsafe {\r
+            let mut destination = ArrayBuilder::new();\r
+\r
+            {\r
+                let (destination_iter, position) = destination.iter_position();\r
+\r
+                iter.into_iter()\r
+                    .zip(destination_iter)\r
+                    .for_each(|(src, dst)| {\r
+                        ptr::write(dst, src);\r
+\r
+                        *position += 1;\r
+                    });\r
+            }\r
+\r
+            if destination.position < N::USIZE {\r
+                from_iter_length_fail(destination.position, N::USIZE);\r
+            }\r
+\r
+            destination.into_inner()\r
+        }\r
+    }\r
+}\r
+\r
+#[inline(never)]\r
+#[cold]\r
+fn from_iter_length_fail(length: usize, expected: usize) -> ! {\r
+    panic!(\r
+        "GenericArray::from_iter received {} elements but expected {}",\r
+        length, expected\r
+    );\r
+}\r
+\r
+unsafe impl<T, N> GenericSequence<T> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+    Self: IntoIterator<Item = T>,\r
+{\r
+    type Length = N;\r
+    type Sequence = Self;\r
+\r
+    fn generate<F>(mut f: F) -> GenericArray<T, N>\r
+    where\r
+        F: FnMut(usize) -> T,\r
+    {\r
+        unsafe {\r
+            let mut destination = ArrayBuilder::new();\r
+\r
+            {\r
+                let (destination_iter, position) = destination.iter_position();\r
+\r
+                destination_iter.enumerate().for_each(|(i, dst)| {\r
+                    ptr::write(dst, f(i));\r
+\r
+                    *position += 1;\r
+                });\r
+            }\r
+\r
+            destination.into_inner()\r
+        }\r
+    }\r
+\r
+    #[doc(hidden)]\r
+    fn inverted_zip<B, U, F>(\r
+        self,\r
+        lhs: GenericArray<B, Self::Length>,\r
+        mut f: F,\r
+    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>\r
+    where\r
+        GenericArray<B, Self::Length>:\r
+            GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,\r
+        Self: MappedGenericSequence<T, U>,\r
+        Self::Length: ArrayLength<B> + ArrayLength<U>,\r
+        F: FnMut(B, Self::Item) -> U,\r
+    {\r
+        unsafe {\r
+            let mut left = ArrayConsumer::new(lhs);\r
+            let mut right = ArrayConsumer::new(self);\r
+\r
+            let (left_array_iter, left_position) = left.iter_position();\r
+            let (right_array_iter, right_position) = right.iter_position();\r
+\r
+            FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {\r
+                let left_value = ptr::read(l);\r
+                let right_value = ptr::read(r);\r
+\r
+                *left_position += 1;\r
+                *right_position += 1;\r
+\r
+                f(left_value, right_value)\r
+            }))\r
+        }\r
+    }\r
+\r
+    #[doc(hidden)]\r
+    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>\r
+    where\r
+        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,\r
+        Self: MappedGenericSequence<T, U>,\r
+        Self::Length: ArrayLength<B> + ArrayLength<U>,\r
+        F: FnMut(Lhs::Item, Self::Item) -> U,\r
+    {\r
+        unsafe {\r
+            let mut right = ArrayConsumer::new(self);\r
+\r
+            let (right_array_iter, right_position) = right.iter_position();\r
+\r
+            FromIterator::from_iter(\r
+                lhs.into_iter()\r
+                    .zip(right_array_iter)\r
+                    .map(|(left_value, r)| {\r
+                        let right_value = ptr::read(r);\r
+\r
+                        *right_position += 1;\r
+\r
+                        f(left_value, right_value)\r
+                    }),\r
+            )\r
+        }\r
+    }\r
+}\r
+\r
+unsafe impl<T, U, N> MappedGenericSequence<T, U> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T> + ArrayLength<U>,\r
+    GenericArray<U, N>: GenericSequence<U, Length = N>,\r
+{\r
+    type Mapped = GenericArray<U, N>;\r
+}\r
+\r
+unsafe impl<T, N> FunctionalSequence<T> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+    Self: GenericSequence<T, Item = T, Length = N>,\r
+{\r
+    fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>\r
+    where\r
+        Self::Length: ArrayLength<U>,\r
+        Self: MappedGenericSequence<T, U>,\r
+        F: FnMut(T) -> U,\r
+    {\r
+        unsafe {\r
+            let mut source = ArrayConsumer::new(self);\r
+\r
+            let (array_iter, position) = source.iter_position();\r
+\r
+            FromIterator::from_iter(array_iter.map(|src| {\r
+                let value = ptr::read(src);\r
+\r
+                *position += 1;\r
+\r
+                f(value)\r
+            }))\r
+        }\r
+    }\r
+\r
+    #[inline]\r
+    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>\r
+    where\r
+        Self: MappedGenericSequence<T, U>,\r
+        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,\r
+        Self::Length: ArrayLength<B> + ArrayLength<U>,\r
+        Rhs: GenericSequence<B, Length = Self::Length>,\r
+        F: FnMut(T, Rhs::Item) -> U,\r
+    {\r
+        rhs.inverted_zip(self, f)\r
+    }\r
+\r
+    fn fold<U, F>(self, init: U, mut f: F) -> U\r
+    where\r
+        F: FnMut(U, T) -> U,\r
+    {\r
+        unsafe {\r
+            let mut source = ArrayConsumer::new(self);\r
+\r
+            let (array_iter, position) = source.iter_position();\r
+\r
+            array_iter.fold(init, |acc, src| {\r
+                let value = ptr::read(src);\r
+\r
+                *position += 1;\r
+\r
+                f(acc, value)\r
+            })\r
+        }\r
+    }\r
+}\r
+\r
+impl<T, N> GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    /// Extracts a slice containing the entire array.\r
+    #[inline]\r
+    pub fn as_slice(&self) -> &[T] {\r
+        self.deref()\r
+    }\r
+\r
+    /// Extracts a mutable slice containing the entire array.\r
+    #[inline]\r
+    pub fn as_mut_slice(&mut self) -> &mut [T] {\r
+        self.deref_mut()\r
+    }\r
+\r
+    /// Converts slice to a generic array reference with inferred length;\r
+    ///\r
+    /// Length of the slice must be equal to the length of the array.\r
+    #[inline]\r
+    pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {\r
+        slice.into()\r
+    }\r
+\r
+    /// Converts mutable slice to a mutable generic array reference\r
+    ///\r
+    /// Length of the slice must be equal to the length of the array.\r
+    #[inline]\r
+    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {\r
+        slice.into()\r
+    }\r
+}\r
+\r
+impl<'a, T, N: ArrayLength<T>> From<&'a [T]> for &'a GenericArray<T, N> {\r
+    /// Converts slice to a generic array reference with inferred length;\r
+    ///\r
+    /// Length of the slice must be equal to the length of the array.\r
+    #[inline]\r
+    fn from(slice: &[T]) -> &GenericArray<T, N> {\r
+        assert_eq!(slice.len(), N::USIZE);\r
+\r
+        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }\r
+    }\r
+}\r
+\r
+impl<'a, T, N: ArrayLength<T>> From<&'a mut [T]> for &'a mut GenericArray<T, N> {\r
+    /// Converts mutable slice to a mutable generic array reference\r
+    ///\r
+    /// Length of the slice must be equal to the length of the array.\r
+    #[inline]\r
+    fn from(slice: &mut [T]) -> &mut GenericArray<T, N> {\r
+        assert_eq!(slice.len(), N::USIZE);\r
+\r
+        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }\r
+    }\r
+}\r
+\r
+impl<T: Clone, N> GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    /// Construct a `GenericArray` from a slice by cloning its content\r
+    ///\r
+    /// Length of the slice must be equal to the length of the array\r
+    #[inline]\r
+    pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {\r
+        Self::from_exact_iter(list.iter().cloned())\r
+            .expect("Slice must be the same length as the array")\r
+    }\r
+}\r
+\r
+impl<T, N> GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+{\r
+    /// Creates a new `GenericArray` instance from an iterator with a specific size.\r
+    ///\r
+    /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`.\r
+    pub fn from_exact_iter<I>(iter: I) -> Option<Self>\r
+    where\r
+        I: IntoIterator<Item = T>,\r
+    {\r
+        let mut iter = iter.into_iter();\r
+\r
+        unsafe {\r
+            let mut destination = ArrayBuilder::new();\r
+\r
+            {\r
+                let (destination_iter, position) = destination.iter_position();\r
+\r
+                destination_iter.zip(&mut iter).for_each(|(dst, src)| {\r
+                    ptr::write(dst, src);\r
+\r
+                    *position += 1;\r
+                });\r
+\r
+                // The iterator produced fewer than `N` elements.\r
+                if *position != N::USIZE {\r
+                    return None;\r
+                }\r
+\r
+                // The iterator produced more than `N` elements.\r
+                if iter.next().is_some() {\r
+                    return None;\r
+                }\r
+            }\r
+\r
+            Some(destination.into_inner())\r
+        }\r
+    }\r
+}\r
+\r
+/// A reimplementation of the `transmute` function, avoiding problems\r
+/// when the compiler can't prove equal sizes.\r
+#[inline]\r
+#[doc(hidden)]\r
+pub unsafe fn transmute<A, B>(a: A) -> B {\r
+    let a = ManuallyDrop::new(a);\r
+    ::core::ptr::read(&*a as *const A as *const B)\r
+}\r
+\r
+#[cfg(test)]\r
+mod test {\r
+    // Compile with:\r
+    // cargo rustc --lib --profile test --release --\r
+    //      -C target-cpu=native -C opt-level=3 --emit asm\r
+    // and view the assembly to make sure test_assembly generates\r
+    // SIMD instructions instead of a naive loop.\r
+\r
+    #[inline(never)]\r
+    pub fn black_box<T>(val: T) -> T {\r
+        use core::{mem, ptr};\r
+\r
+        let ret = unsafe { ptr::read_volatile(&val) };\r
+        mem::forget(val);\r
+        ret\r
+    }\r
+\r
+    #[test]\r
+    fn test_assembly() {\r
+        use crate::functional::*;\r
+\r
+        let a = black_box(arr![i32; 1, 3, 5, 7]);\r
+        let b = black_box(arr![i32; 2, 4, 6, 8]);\r
+\r
+        let c = (&a).zip(b, |l, r| l + r);\r
+\r
+        let d = a.fold(0, |a, x| a + x);\r
+\r
+        assert_eq!(c, arr![i32; 3, 7, 11, 15]);\r
+\r
+        assert_eq!(d, 16);\r
+    }\r
+}\r
diff --git a/src/sequence.rs b/src/sequence.rs
new file mode 100644 (file)
index 0000000..0119d3d
--- /dev/null
@@ -0,0 +1,380 @@
+//! Useful traits for manipulating sequences of data stored in `GenericArray`s\r
+\r
+use super::*;\r
+use core::ops::{Add, Sub};\r
+use core::mem::MaybeUninit;\r
+use core::ptr;\r
+use typenum::operator_aliases::*;\r
+\r
+/// Defines some sequence with an associated length and iteration capabilities.\r
+///\r
+/// This is useful for passing N-length generic arrays as generics.\r
+pub unsafe trait GenericSequence<T>: Sized + IntoIterator {\r
+    /// `GenericArray` associated length\r
+    type Length: ArrayLength<T>;\r
+\r
+    /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence`\r
+    type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;\r
+\r
+    /// Initializes a new sequence instance using the given function.\r
+    ///\r
+    /// If the generator function panics while initializing the sequence,\r
+    /// any already initialized elements will be dropped.\r
+    fn generate<F>(f: F) -> Self::Sequence\r
+    where\r
+        F: FnMut(usize) -> T;\r
+\r
+    #[doc(hidden)]\r
+    fn inverted_zip<B, U, F>(\r
+        self,\r
+        lhs: GenericArray<B, Self::Length>,\r
+        mut f: F,\r
+    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>\r
+    where\r
+        GenericArray<B, Self::Length>: GenericSequence<B, Length = Self::Length>\r
+            + MappedGenericSequence<B, U>,\r
+        Self: MappedGenericSequence<T, U>,\r
+        Self::Length: ArrayLength<B> + ArrayLength<U>,\r
+        F: FnMut(B, Self::Item) -> U,\r
+    {\r
+        unsafe {\r
+            let mut left = ArrayConsumer::new(lhs);\r
+\r
+            let (left_array_iter, left_position) = left.iter_position();\r
+\r
+            FromIterator::from_iter(left_array_iter.zip(self.into_iter()).map(\r
+                |(l, right_value)| {\r
+                        let left_value = ptr::read(l);\r
+\r
+                        *left_position += 1;\r
+\r
+                        f(left_value, right_value)\r
+                },\r
+            ))\r
+        }\r
+    }\r
+\r
+    #[doc(hidden)]\r
+    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>\r
+    where\r
+        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,\r
+        Self: MappedGenericSequence<T, U>,\r
+        Self::Length: ArrayLength<B> + ArrayLength<U>,\r
+        F: FnMut(Lhs::Item, Self::Item) -> U,\r
+    {\r
+        FromIterator::from_iter(lhs.into_iter().zip(self.into_iter()).map(|(l, r)| f(l, r)))\r
+    }\r
+}\r
+\r
+/// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item`\r
+///\r
+/// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`,\r
+/// this can be useful for keeping things organized.\r
+pub type SequenceItem<T> = <T as IntoIterator>::Item;\r
+\r
+unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S\r
+where\r
+    &'a S: IntoIterator,\r
+{\r
+    type Length = S::Length;\r
+    type Sequence = S::Sequence;\r
+\r
+    #[inline]\r
+    fn generate<F>(f: F) -> Self::Sequence\r
+    where\r
+        F: FnMut(usize) -> T,\r
+    {\r
+        S::generate(f)\r
+    }\r
+}\r
+\r
+unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S\r
+where\r
+    &'a mut S: IntoIterator,\r
+{\r
+    type Length = S::Length;\r
+    type Sequence = S::Sequence;\r
+\r
+    #[inline]\r
+    fn generate<F>(f: F) -> Self::Sequence\r
+    where\r
+        F: FnMut(usize) -> T,\r
+    {\r
+        S::generate(f)\r
+    }\r
+}\r
+\r
+/// Defines any `GenericSequence` which can be lengthened or extended by appending\r
+/// or prepending an element to it.\r
+///\r
+/// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back`\r
+pub unsafe trait Lengthen<T>: Sized + GenericSequence<T> {\r
+    /// `GenericSequence` that has one more element than `Self`\r
+    type Longer: Shorten<T, Shorter = Self>;\r
+\r
+    /// Returns a new array with the given element appended to the end of it.\r
+    ///\r
+    /// Example:\r
+    ///\r
+    /// ```rust\r
+    /// # use generic_array::{arr, sequence::Lengthen};\r
+    /// # fn main() {\r
+    /// let a = arr![i32; 1, 2, 3];\r
+    ///\r
+    /// let b = a.append(4);\r
+    ///\r
+    /// assert_eq!(b, arr![i32; 1, 2, 3, 4]);\r
+    /// # }\r
+    /// ```\r
+    fn append(self, last: T) -> Self::Longer;\r
+\r
+    /// Returns a new array with the given element prepended to the front of it.\r
+    ///\r
+    /// Example:\r
+    ///\r
+    /// ```rust\r
+    /// # use generic_array::{arr, sequence::Lengthen};\r
+    /// # fn main() {\r
+    /// let a = arr![i32; 1, 2, 3];\r
+    ///\r
+    /// let b = a.prepend(4);\r
+    ///\r
+    /// assert_eq!(b, arr![i32; 4, 1, 2, 3]);\r
+    /// # }\r
+    /// ```\r
+    fn prepend(self, first: T) -> Self::Longer;\r
+}\r
+\r
+/// Defines a `GenericSequence` which can be shortened by removing the first or last element from it.\r
+///\r
+/// Additionally, any shortened sequence can be lengthened by\r
+/// appending or prepending an element to it.\r
+pub unsafe trait Shorten<T>: Sized + GenericSequence<T> {\r
+    /// `GenericSequence` that has one less element than `Self`\r
+    type Shorter: Lengthen<T, Longer = Self>;\r
+\r
+    /// Returns a new array without the last element, and the last element.\r
+    ///\r
+    /// Example:\r
+    ///\r
+    /// ```rust\r
+    /// # use generic_array::{arr, sequence::Shorten};\r
+    /// # fn main() {\r
+    /// let a = arr![i32; 1, 2, 3, 4];\r
+    ///\r
+    /// let (init, last) = a.pop_back();\r
+    ///\r
+    /// assert_eq!(init, arr![i32; 1, 2, 3]);\r
+    /// assert_eq!(last, 4);\r
+    /// # }\r
+    /// ```\r
+    fn pop_back(self) -> (Self::Shorter, T);\r
+\r
+    /// Returns a new array without the first element, and the first element.\r
+    /// Example:\r
+    ///\r
+    /// ```rust\r
+    /// # use generic_array::{arr, sequence::Shorten};\r
+    /// # fn main() {\r
+    /// let a = arr![i32; 1, 2, 3, 4];\r
+    ///\r
+    /// let (head, tail) = a.pop_front();\r
+    ///\r
+    /// assert_eq!(head, 1);\r
+    /// assert_eq!(tail, arr![i32; 2, 3, 4]);\r
+    /// # }\r
+    /// ```\r
+    fn pop_front(self) -> (T, Self::Shorter);\r
+}\r
+\r
+unsafe impl<T, N: ArrayLength<T>> Lengthen<T> for GenericArray<T, N>\r
+where\r
+    N: Add<B1>,\r
+    Add1<N>: ArrayLength<T>,\r
+    Add1<N>: Sub<B1, Output = N>,\r
+    Sub1<Add1<N>>: ArrayLength<T>,\r
+{\r
+    type Longer = GenericArray<T, Add1<N>>;\r
+\r
+    fn append(self, last: T) -> Self::Longer {\r
+        let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();\r
+\r
+        // Note this is *mut Self, so add(1) increments by the whole array\r
+        let out_ptr = longer.as_mut_ptr() as *mut Self;\r
+\r
+        unsafe {\r
+            // write self first\r
+            ptr::write(out_ptr, self);\r
+            // increment past self, then write the last\r
+            ptr::write(out_ptr.add(1) as *mut T, last);\r
+\r
+            longer.assume_init()\r
+        }\r
+    }\r
+\r
+    fn prepend(self, first: T) -> Self::Longer {\r
+        let mut longer: MaybeUninit<Self::Longer> = MaybeUninit::uninit();\r
+\r
+        // Note this is *mut T, so add(1) increments by a single T\r
+        let out_ptr = longer.as_mut_ptr() as *mut T;\r
+\r
+        unsafe {\r
+            // write the first at the start\r
+            ptr::write(out_ptr, first);\r
+            // increment past the first, then write self\r
+            ptr::write(out_ptr.add(1) as *mut Self, self);\r
+\r
+            longer.assume_init()\r
+        }\r
+    }\r
+}\r
+\r
+unsafe impl<T, N: ArrayLength<T>> Shorten<T> for GenericArray<T, N>\r
+where\r
+    N: Sub<B1>,\r
+    Sub1<N>: ArrayLength<T>,\r
+    Sub1<N>: Add<B1, Output = N>,\r
+    Add1<Sub1<N>>: ArrayLength<T>,\r
+{\r
+    type Shorter = GenericArray<T, Sub1<N>>;\r
+\r
+    fn pop_back(self) -> (Self::Shorter, T) {\r
+        let whole = ManuallyDrop::new(self);\r
+\r
+        unsafe {\r
+            let init = ptr::read(whole.as_ptr() as _);\r
+            let last = ptr::read(whole.as_ptr().add(Sub1::<N>::USIZE) as _);\r
+\r
+            (init, last)\r
+        }\r
+    }\r
+\r
+    fn pop_front(self) -> (T, Self::Shorter) {\r
+        // ensure this doesn't get dropped\r
+        let whole = ManuallyDrop::new(self);\r
+\r
+        unsafe {\r
+            let head = ptr::read(whole.as_ptr() as _);\r
+            let tail = ptr::read(whole.as_ptr().offset(1) as _);\r
+\r
+            (head, tail)\r
+        }\r
+    }\r
+}\r
+\r
+/// Defines a `GenericSequence` that can be split into two parts at a given pivot index.\r
+pub unsafe trait Split<T, K>: GenericSequence<T>\r
+where\r
+    K: ArrayLength<T>,\r
+{\r
+    /// First part of the resulting split array\r
+    type First: GenericSequence<T>;\r
+    /// Second part of the resulting split array\r
+    type Second: GenericSequence<T>;\r
+\r
+    /// Splits an array at the given index, returning the separate parts of the array.\r
+    fn split(self) -> (Self::First, Self::Second);\r
+}\r
+\r
+unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+    K: ArrayLength<T>,\r
+    N: Sub<K>,\r
+    Diff<N, K>: ArrayLength<T>,\r
+{\r
+    type First = GenericArray<T, K>;\r
+    type Second = GenericArray<T, Diff<N, K>>;\r
+\r
+    fn split(self) -> (Self::First, Self::Second) {\r
+        unsafe {\r
+            // ensure this doesn't get dropped\r
+            let whole = ManuallyDrop::new(self);\r
+\r
+            let head = ptr::read(whole.as_ptr() as *const _);\r
+            let tail = ptr::read(whole.as_ptr().add(K::USIZE) as *const _);\r
+\r
+            (head, tail)\r
+        }\r
+    }\r
+}\r
+\r
+unsafe impl<'a, T, N, K> Split<T, K> for &'a GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+    K: ArrayLength<T> + 'static,\r
+    N: Sub<K>,\r
+    Diff<N, K>: ArrayLength<T>,\r
+{\r
+    type First = &'a GenericArray<T, K>;\r
+    type Second = &'a GenericArray<T, Diff<N, K>>;\r
+\r
+    fn split(self) -> (Self::First, Self::Second) {\r
+        unsafe {\r
+            let ptr_to_first: *const T = self.as_ptr();\r
+            let head = &*(ptr_to_first as *const _);\r
+            let tail = &*(ptr_to_first.add(K::USIZE) as *const _);\r
+            (head, tail)\r
+        }\r
+    }\r
+}\r
+\r
+unsafe impl<'a, T, N, K> Split<T, K> for &'a mut GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T>,\r
+    K: ArrayLength<T> + 'static,\r
+    N: Sub<K>,\r
+    Diff<N, K>: ArrayLength<T>,\r
+{\r
+    type First = &'a mut GenericArray<T, K>;\r
+    type Second = &'a mut GenericArray<T, Diff<N, K>>;\r
+\r
+    fn split(self) -> (Self::First, Self::Second) {\r
+        unsafe {\r
+            let ptr_to_first: *mut T = self.as_mut_ptr();\r
+            let head = &mut *(ptr_to_first as *mut _);\r
+            let tail = &mut *(ptr_to_first.add(K::USIZE) as *mut _);\r
+            (head, tail)\r
+        }\r
+    }\r
+}\r
+\r
+/// Defines `GenericSequence`s which can be joined together, forming a larger array.\r
+pub unsafe trait Concat<T, M>: GenericSequence<T>\r
+where\r
+    M: ArrayLength<T>,\r
+{\r
+    /// Sequence to be concatenated with `self`\r
+    type Rest: GenericSequence<T, Length = M>;\r
+\r
+    /// Resulting sequence formed by the concatenation.\r
+    type Output: GenericSequence<T>;\r
+\r
+    /// Concatenate, or join, two sequences.\r
+    fn concat(self, rest: Self::Rest) -> Self::Output;\r
+}\r
+\r
+unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>\r
+where\r
+    N: ArrayLength<T> + Add<M>,\r
+    M: ArrayLength<T>,\r
+    Sum<N, M>: ArrayLength<T>,\r
+{\r
+    type Rest = GenericArray<T, M>;\r
+    type Output = GenericArray<T, Sum<N, M>>;\r
+\r
+    fn concat(self, rest: Self::Rest) -> Self::Output {\r
+        let mut output: MaybeUninit<Self::Output> = MaybeUninit::uninit();\r
+\r
+        let out_ptr = output.as_mut_ptr() as *mut Self;\r
+\r
+        unsafe {\r
+            // write all of self to the pointer\r
+            ptr::write(out_ptr, self);\r
+            // increment past self, then write the rest\r
+            ptr::write(out_ptr.add(1) as *mut _, rest);\r
+\r
+            output.assume_init()\r
+        }\r
+    }\r
+}\r