Skip to content

Commit 7b3efcf

Browse files
committed
Extra crate support, try_generate, try_fold
1 parent f41a2ff commit 7b3efcf

File tree

15 files changed

+241
-29
lines changed

15 files changed

+241
-29
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
uses: dtolnay/rust-toolchain@nightly
3939

4040
- name: Build documentation
41-
run: cargo doc --features "serde zeroize const-default alloc hybrid-array-0_4"
41+
run: cargo doc --features "serde zeroize const-default alloc hybrid-array-0_4 subtle arbitrary bytemuck"
4242

4343
- name: Finalize documentation
4444
run: |

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* **`1.3.5`**
2+
* Add `subtle`, `arbitrary`, and `bytemuck` implementations for `GenericArray` when the inner type supports them.
3+
* Add `FallibleGenericSequence` with `try_generate` for fallible generation of sequences/arrays.
4+
* Add `try_fold` to `FunctionalSequence` for fallible folding of sequences/arrays.
5+
16
* **`1.3.4`**
27
* Significantly improve stack usage of `GenericArray` methods in unoptimized (`-C opt-level=0`) build modes.
38
* Introduce the `hybrid-array-0_4` feature to allow interop between `generic-array` 1.x and `hybrid-array` 0.4 versions.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ const-default = { version = "1", optional = true, default-features = false }
3333
serde_core = { version = "1.0", optional = true, default-features = false }
3434
zeroize = { version = "1", optional = true, default-features = false }
3535
faster-hex = { version = "0.10", optional = true, default-features = false }
36+
subtle = { version = "2", optional = true, default-features = false }
37+
arbitrary = { version = "1", optional = true, default-features = false }
38+
bytemuck = { version = "1", optional = true, default-features = false }
3639
rustversion = "1"
3740

3841
generic_array-0_14 = { package = "generic-array", version = "0.14", optional = true, default-features = false }
@@ -57,7 +60,7 @@ codegen-units = 1
5760

5861
[package.metadata.docs.rs]
5962
# all but "internals", don't show those on docs.rs
60-
features = ["serde", "zeroize", "const-default", "alloc", "hybrid-array-0_4"]
63+
features = ["serde", "zeroize", "const-default", "alloc", "hybrid-array-0_4", "subtle", "arbitrary", "bytemuck"]
6164
rustdoc-args = ["--cfg", "docsrs"]
6265

6366
[package.metadata.playground]

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array)
22
[![Build Status](https://github.com/fizyk20/generic-array/actions/workflows/CI.yml/badge.svg)](https://github.com/fizyk20/generic-array/actions/workflows/CI.yml)
3+
![Rust Version](https://img.shields.io/badge/rustc-1.65+-blue.svg)
4+
35
# generic-array
46

57
This crate implements a structure that can be used as a generic array type.
@@ -126,6 +128,10 @@ features = [
126128
"const-default", # Compile-time const default value support via trait
127129
"alloc", # Enables From/TryFrom implementations between GenericArray and Vec<T>/Box<[T]>
128130
"faster-hex", # Enables internal use of the `faster-hex` crate for faster hex encoding via SIMD
131+
"subtle", # Enables `subtle` crate support for constant-time equality checks and conditional selection
132+
"arbitrary", # Enables `arbitrary` crate support for fuzzing
133+
"bytemuck", # Enables `bytemuck` crate support
134+
"compat-0_14", # Enables interoperability with `generic-array` 0.14
129135
"compat-0_14", # Enables interoperability with `generic-array` 0.14
130136
"hybrid-array-0_4" # Enables interoperability with `hybrid-array` 0.4
131137
]

src/ext_impls/impl_arbitrary.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use arbitrary::Arbitrary;
2+
3+
use crate::{sequence::FallibleGenericSequence as _, ArrayLength, GenericArray};
4+
5+
impl<'a, T, N: ArrayLength> Arbitrary<'a> for GenericArray<T, N>
6+
where
7+
T: Arbitrary<'a>,
8+
{
9+
#[inline]
10+
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
11+
GenericArray::try_generate(|_| T::arbitrary(u))
12+
}
13+
14+
#[inline]
15+
fn arbitrary_take_rest(mut u: arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
16+
let mut array = Self::arbitrary(&mut u)?;
17+
if let Some(last) = array.last_mut() {
18+
*last = T::arbitrary_take_rest(u)?;
19+
}
20+
Ok(array)
21+
}
22+
23+
fn size_hint(depth: usize) -> (usize, Option<usize>) {
24+
Self::try_size_hint(depth).unwrap_or_default()
25+
}
26+
27+
fn try_size_hint(
28+
depth: usize,
29+
) -> arbitrary::Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
30+
let hint = <T as Arbitrary>::try_size_hint(depth)?;
31+
32+
// same as `arbitrary::size_hint::and_all(...)` but without allocations
33+
Ok(core::iter::repeat(hint)
34+
.take(N::USIZE)
35+
.fold((0, Some(0)), arbitrary::size_hint::and))
36+
}
37+
}

src/ext_impls/impl_bytemuck.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use bytemuck::{Pod, Zeroable};
2+
3+
use crate::{ArrayLength, GenericArray};
4+
5+
unsafe impl<T: Pod, N: ArrayLength> Pod for GenericArray<T, N> where GenericArray<T, N>: Copy {}
6+
7+
unsafe impl<T: Zeroable, N: ArrayLength> Zeroable for GenericArray<T, N> {}

src/ext_impls/impl_subtle.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use subtle::{ConditionallySelectable, ConstantTimeEq};
2+
3+
use crate::{ArrayLength, GenericArray};
4+
5+
impl<T, N: ArrayLength> ConstantTimeEq for GenericArray<T, N>
6+
where
7+
T: ConstantTimeEq,
8+
{
9+
#[inline]
10+
fn ct_eq(&self, other: &Self) -> subtle::Choice {
11+
self.as_slice().ct_eq(other.as_slice())
12+
}
13+
}
14+
15+
impl<T, N: ArrayLength> ConditionallySelectable for GenericArray<T, N>
16+
where
17+
GenericArray<T, N>: Copy,
18+
T: ConditionallySelectable,
19+
{
20+
#[inline]
21+
fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
22+
let mut out = *a;
23+
out.conditional_assign(b, choice);
24+
out
25+
}
26+
27+
#[inline]
28+
fn conditional_assign(&mut self, other: &Self, choice: subtle::Choice) {
29+
for (a, b) in self.iter_mut().zip(other.iter()) {
30+
a.conditional_assign(b, choice);
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)