--- /dev/null
+{
+ "git": {
+ "sha1": "bd2832933f655cd58b59a0e5a57dd6941a3d0322"
+ },
+ "path_in_vcs": ""
+}
\ No newline at end of file
--- /dev/null
+* **`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
--- /dev/null
+# 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"
--- /dev/null
+[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
--- /dev/null
+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
--- /dev/null
+[](https://crates.io/crates/generic-array)\r
+[](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
--- /dev/null
+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
--- /dev/null
+//! 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
--- /dev/null
+//! 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
--- /dev/null
+//! 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
--- /dev/null
+//! 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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+//! `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
--- /dev/null
+//! 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
--- /dev/null
+//! 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