Skip to content

Commit 88341ba

Browse files
committed
Add v3-preview module gathering a few breaking changes
This new module addresses the following breaking changes of #72: - `static` instead of `const` for pre-defined encodings - Private `Encoding` implementation with `unsafe` constructor - Use `MaybeUninit` internally and expose `_uninit` functions - Use static dispatch instead of dynamic dispatch (fixing #97)
1 parent 18203b9 commit 88341ba

File tree

5 files changed

+1186
-7
lines changed

5 files changed

+1186
-7
lines changed

lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ rustdoc-args = ["--cfg=docsrs"]
2121
default = ["std"]
2222
alloc = []
2323
std = ["alloc"]
24+
v3-preview = []

lib/fuzz/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,10 @@ name = "encode_write"
2929
path = "fuzz_targets/encode_write.rs"
3030
test = false
3131
doc = false
32+
33+
[[bin]]
34+
name = "v3-preview"
35+
path = "fuzz_targets/v3-preview.rs"
36+
test = false
37+
doc = false
38+
required-features = ["data-encoding/v3-preview"]

lib/fuzz/fuzz_targets/v3-preview.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#![no_main]
2+
3+
use data_encoding::v3_preview::{Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Encoding, False, True};
4+
use data_encoding_fuzz::{decode_prefix, generate_encoding};
5+
use libfuzzer_sys::fuzz_target;
6+
7+
fuzz_target!(|data: &[u8]| {
8+
let mut data = data;
9+
let dyn_base = generate_encoding(&mut data);
10+
let mut count = 0;
11+
macro_rules! test {
12+
($Bit:ident, $Msb:ident, $Pad:ident, $Wrap:ident, $Ignore:ident) => {
13+
if let Ok(base) = <&Encoding<$Bit, $Msb, $Pad, $Wrap, $Ignore>>::try_from(&dyn_base) {
14+
count += 1;
15+
let encoded = base.encode(data);
16+
assert_eq!(encoded, dyn_base.encode(data));
17+
assert_eq!(base.decode(encoded.as_bytes()).unwrap(), data);
18+
if dyn_base.is_canonical() {
19+
let raw = decode_prefix(&dyn_base, &mut data);
20+
assert_eq!(base.encode(&raw).as_bytes(), data);
21+
}
22+
}
23+
};
24+
}
25+
test!(Bit1, False, False, False, False);
26+
test!(Bit1, False, False, False, True);
27+
test!(Bit1, False, False, True, True);
28+
test!(Bit1, False, True, False, False);
29+
test!(Bit1, False, True, False, True);
30+
test!(Bit1, False, True, True, True);
31+
test!(Bit1, True, False, False, False);
32+
test!(Bit1, True, False, False, True);
33+
test!(Bit1, True, False, True, True);
34+
test!(Bit1, True, True, False, False);
35+
test!(Bit1, True, True, False, True);
36+
test!(Bit1, True, True, True, True);
37+
test!(Bit2, False, False, False, False);
38+
test!(Bit2, False, False, False, True);
39+
test!(Bit2, False, False, True, True);
40+
test!(Bit2, False, True, False, False);
41+
test!(Bit2, False, True, False, True);
42+
test!(Bit2, False, True, True, True);
43+
test!(Bit2, True, False, False, False);
44+
test!(Bit2, True, False, False, True);
45+
test!(Bit2, True, False, True, True);
46+
test!(Bit2, True, True, False, False);
47+
test!(Bit2, True, True, False, True);
48+
test!(Bit2, True, True, True, True);
49+
test!(Bit3, False, False, False, False);
50+
test!(Bit3, False, False, False, True);
51+
test!(Bit3, False, False, True, True);
52+
test!(Bit3, False, True, False, False);
53+
test!(Bit3, False, True, False, True);
54+
test!(Bit3, False, True, True, True);
55+
test!(Bit3, True, False, False, False);
56+
test!(Bit3, True, False, False, True);
57+
test!(Bit3, True, False, True, True);
58+
test!(Bit3, True, True, False, False);
59+
test!(Bit3, True, True, False, True);
60+
test!(Bit3, True, True, True, True);
61+
test!(Bit4, False, False, False, False);
62+
test!(Bit4, False, False, False, True);
63+
test!(Bit4, False, False, True, True);
64+
test!(Bit4, False, True, False, False);
65+
test!(Bit4, False, True, False, True);
66+
test!(Bit4, False, True, True, True);
67+
test!(Bit4, True, False, False, False);
68+
test!(Bit4, True, False, False, True);
69+
test!(Bit4, True, False, True, True);
70+
test!(Bit4, True, True, False, False);
71+
test!(Bit4, True, True, False, True);
72+
test!(Bit4, True, True, True, True);
73+
test!(Bit5, False, False, False, False);
74+
test!(Bit5, False, False, False, True);
75+
test!(Bit5, False, False, True, True);
76+
test!(Bit5, False, True, False, False);
77+
test!(Bit5, False, True, False, True);
78+
test!(Bit5, False, True, True, True);
79+
test!(Bit5, True, False, False, False);
80+
test!(Bit5, True, False, False, True);
81+
test!(Bit5, True, False, True, True);
82+
test!(Bit5, True, True, False, False);
83+
test!(Bit5, True, True, False, True);
84+
test!(Bit5, True, True, True, True);
85+
test!(Bit6, False, False, False, False);
86+
test!(Bit6, False, False, False, True);
87+
test!(Bit6, False, False, True, True);
88+
test!(Bit6, False, True, False, False);
89+
test!(Bit6, False, True, False, True);
90+
test!(Bit6, False, True, True, True);
91+
test!(Bit6, True, False, False, False);
92+
test!(Bit6, True, False, False, True);
93+
test!(Bit6, True, False, True, True);
94+
test!(Bit6, True, True, False, False);
95+
test!(Bit6, True, True, False, True);
96+
test!(Bit6, True, True, True, True);
97+
assert_eq!(count, 1);
98+
});

lib/src/lib.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ macro_rules! check {
184184
};
185185
}
186186

187+
#[cfg(feature = "v3-preview")]
188+
pub mod v3_preview;
189+
187190
trait Static<T: Copy>: Copy {
188191
fn val(self) -> T;
189192
}
@@ -255,21 +258,21 @@ macro_rules! dispatch {
255258
($body: expr) => { $body };
256259
}
257260

258-
unsafe fn chunk_unchecked(x: &[u8], n: usize, i: usize) -> &[u8] {
261+
unsafe fn chunk_unchecked<T>(x: &[T], n: usize, i: usize) -> &[T] {
259262
debug_assert!((i + 1) * n <= x.len());
260263
unsafe { core::slice::from_raw_parts(x.as_ptr().add(n * i), n) }
261264
}
262265

263-
unsafe fn chunk_mut_unchecked(x: &mut [u8], n: usize, i: usize) -> &mut [u8] {
266+
unsafe fn chunk_mut_unchecked<T>(x: &mut [T], n: usize, i: usize) -> &mut [T] {
264267
debug_assert!((i + 1) * n <= x.len());
265268
unsafe { core::slice::from_raw_parts_mut(x.as_mut_ptr().add(n * i), n) }
266269
}
267270

268-
fn div_ceil(x: usize, m: usize) -> usize {
271+
const fn div_ceil(x: usize, m: usize) -> usize {
269272
(x + m - 1) / m
270273
}
271274

272-
fn floor(x: usize, m: usize) -> usize {
275+
const fn floor(x: usize, m: usize) -> usize {
273276
x / m * m
274277
}
275278

@@ -354,15 +357,15 @@ const INVALID: u8 = 128;
354357
const IGNORE: u8 = 129;
355358
const PADDING: u8 = 130;
356359

357-
fn order(msb: bool, n: usize, i: usize) -> usize {
360+
const fn order(msb: bool, n: usize, i: usize) -> usize {
358361
if msb {
359362
n - 1 - i
360363
} else {
361364
i
362365
}
363366
}
364367

365-
fn enc(bit: usize) -> usize {
368+
const fn enc(bit: usize) -> usize {
366369
match bit {
367370
1 | 2 | 4 => 1,
368371
3 | 6 => 3,
@@ -371,7 +374,7 @@ fn enc(bit: usize) -> usize {
371374
}
372375
}
373376

374-
fn dec(bit: usize) -> usize {
377+
const fn dec(bit: usize) -> usize {
375378
enc(bit) * 8 / bit
376379
}
377380

@@ -880,6 +883,7 @@ pub type InternalEncoding = &'static [u8];
880883
// - width % dec(bit) == 0
881884
// - for all x in separator values[x] is IGNORE
882885
#[derive(Debug, Clone, PartialEq, Eq)]
886+
#[repr(transparent)]
883887
pub struct Encoding(#[doc(hidden)] pub InternalEncoding);
884888

885889
/// How to translate characters when decoding

0 commit comments

Comments
 (0)