• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ia0 / data-encoding / #1030

28 Jun 2025 04:09PM UTC coverage: 52.853%. Remained the same
#1030

push

web-flow
Fix lint in xtask (#144)

491 of 929 relevant lines covered (52.85%)

2.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
lib/fuzz/src/gen.rs
1
use data_encoding::{Encoding, Specification};
2

3
pub fn base(data: &mut &[u8]) -> Encoding {
4
    spec(data).encoding().unwrap()
5
}
6

7
pub fn spec(data: &mut &[u8]) -> Specification {
8
    let mut spec = Specification::new();
9
    let mut ascii = Ascii::new();
10
    let bit = generate(data, 1, 6);
11
    for _ in 0 .. 1 << bit {
12
        spec.symbols.push(ascii.next_free(data));
13
    }
14
    if generate(data, 0, 1) == 1 {
15
        spec.bit_order = data_encoding::BitOrder::LeastSignificantFirst;
16
    }
17
    if generate(data, 0, 1) == 1 {
18
        spec.check_trailing_bits = false;
19
    }
20
    if !8u8.is_multiple_of(bit) && generate(data, 0, 1) == 1 {
21
        spec.padding = Some(ascii.next_free(data));
22
    }
23
    let ignore_translate_len = generate(data, 0, ascii.len_free());
24
    let ignore_len = generate(data, 0, ignore_translate_len);
25
    let translate_len = ignore_translate_len - ignore_len;
26
    for _ in 0 .. ignore_len {
27
        spec.ignore.push(ascii.next_free(data));
28
    }
29
    if !spec.ignore.is_empty() {
30
        let dec = match bit {
31
            1 | 3 | 5 => 8,
32
            2 | 6 => 4,
33
            4 => 2,
34
            _ => unreachable!(),
35
        };
36
        spec.wrap.width = generate(data, 0, 255) as usize / dec * dec;
37
        if spec.wrap.width > 0 {
38
            for _ in 0 .. generate(data, 1, 255) {
39
                spec.wrap.separator.push(Ascii::next(spec.ignore.as_bytes(), data));
40
            }
41
        }
42
    }
43
    for _ in 0 .. translate_len {
44
        spec.translate.to.push(ascii.next_used(data));
45
    }
46
    for _ in 0 .. translate_len {
47
        spec.translate.from.push(ascii.next_free(data));
48
    }
49
    spec
50
}
51

52
pub fn rev_spec(spec: &Specification) -> Vec<u8> {
53
    assert!(spec.encoding().is_ok());
54
    let mut output = Vec::new();
55
    let mut ascii = Ascii::new();
56
    let bit = spec.symbols.len().trailing_zeros() as u8;
57
    output.push(bit - 1);
58
    for x in spec.symbols.bytes() {
59
        output.push(ascii.rev_free(x));
60
    }
61
    output.push((spec.bit_order == data_encoding::BitOrder::LeastSignificantFirst) as u8);
62
    output.push(!spec.check_trailing_bits as u8);
63
    if !8u8.is_multiple_of(bit) {
64
        output.push(spec.padding.is_some() as u8);
65
        if let Some(pad) = spec.padding {
66
            output.push(ascii.rev_free(pad as u8));
67
        }
68
    }
69
    output.push((spec.ignore.len() + spec.translate.from.len()) as u8);
70
    output.push(spec.ignore.len() as u8);
71
    for x in spec.ignore.bytes() {
72
        output.push(ascii.rev_free(x));
73
    }
74
    if !spec.ignore.is_empty() {
75
        output.push(spec.wrap.width as u8);
76
        if 0 < spec.wrap.width {
77
            output.push(spec.wrap.separator.len() as u8 - 1);
78
            for x in spec.wrap.separator.bytes() {
79
                output.push(Ascii::rev(spec.ignore.as_bytes(), x));
80
            }
81
        }
82
    }
83
    for x in spec.translate.to.bytes() {
84
        output.push(ascii.rev_used(x));
85
    }
86
    for x in spec.translate.from.bytes() {
87
        output.push(ascii.rev_free(x));
88
    }
89
    output
90
}
91

92
pub fn any_spec(data: &mut &[u8]) -> Option<Specification> {
93
    let symbols = string(data)?;
94
    let bit_order = match flip(data) {
95
        false => data_encoding::BitOrder::LeastSignificantFirst,
96
        true => data_encoding::BitOrder::MostSignificantFirst,
97
    };
98
    let check_trailing_bits = flip(data);
99
    let padding = string(data)?.pop();
100
    let ignore = string(data)?;
101
    let width = generate(data, 0, 255) as usize;
102
    let separator = string(data)?;
103
    let wrap = data_encoding::Wrap { width, separator };
104
    let from = string(data)?;
105
    let to = string(data)?;
106
    let translate = data_encoding::Translate { from, to };
107
    Some(Specification {
108
        symbols,
109
        bit_order,
110
        check_trailing_bits,
111
        padding,
112
        ignore,
113
        wrap,
114
        translate,
115
    })
116
}
117

118
pub fn bytes<'a>(data: &'_ mut &'a [u8], len: usize) -> &'a [u8] {
×
119
    let len = std::cmp::min(len, data.len());
×
120
    let res = &data[.. len];
×
121
    *data = &data[len ..];
×
122
    res
×
123
}
124

125
pub fn nat(data: &mut &[u8], min: usize, max: usize) -> usize {
126
    let log = match (max - min).checked_ilog2() {
127
        None => return min,
128
        Some(x) => x,
129
    };
130
    let mut res = 0;
131
    for _ in 0 .. log / 8 + 1 {
132
        res = (res << 8) | generate(data, 0, 255) as usize;
133
    }
134
    if usize::MIN < min || max < usize::MAX {
135
        res = min + res % (max - min + 1);
136
    }
137
    res
138
}
139

140
fn flip(data: &mut &[u8]) -> bool {
141
    generate(data, 0, 1) == 1
142
}
143

144
fn string(data: &mut &[u8]) -> Option<String> {
145
    let len = generate(data, 0, 255) as usize;
146
    String::from_utf8(bytes(data, len).to_vec()).ok()
147
}
148

149
fn generate(data: &mut &[u8], min: u8, max: u8) -> u8 {
150
    if data.is_empty() {
151
        return min;
152
    }
153
    let mut res = data[0];
154
    if min > 0 || max < 255 {
155
        res = min + data[0] % (max - min + 1);
156
    }
157
    *data = &data[1 ..];
158
    res
159
}
160

161
struct Ascii {
162
    free: Vec<u8>,
163
    used: Vec<u8>,
164
}
165

166
impl Ascii {
167
    fn new() -> Ascii {
168
        Ascii { free: (0 .. 128).collect(), used: Vec::with_capacity(128) }
169
    }
170

171
    fn next_free(&mut self, data: &mut &[u8]) -> char {
172
        let res = self.free.swap_remove(generate(data, 0, self.len_free() - 1) as usize);
173
        self.used.push(res);
174
        res as char
175
    }
176

177
    fn rev_free(&mut self, x: u8) -> u8 {
178
        let i = self.free.iter().position(|&y| x == y).unwrap();
179
        assert_eq!(self.free.swap_remove(i), x);
180
        self.used.push(x);
181
        i as u8
182
    }
183

184
    fn next_used(&self, data: &mut &[u8]) -> char {
185
        Ascii::next(&self.used, data)
186
    }
187

188
    fn rev_used(&self, x: u8) -> u8 {
189
        Ascii::rev(&self.used, x)
190
    }
191

192
    fn next(input: &[u8], data: &mut &[u8]) -> char {
193
        input[generate(data, 0, input.len() as u8 - 1) as usize] as char
194
    }
195

196
    fn rev(input: &[u8], x: u8) -> u8 {
197
        input.iter().position(|&y| x == y).unwrap() as u8
198
    }
199

200
    fn len_free(&self) -> u8 {
201
        self.free.len() as u8
202
    }
203
}
204

205
#[cfg(test)]
206
mod tests {
207
    use super::*;
208

209
    #[test]
210
    fn nat_ok() {
211
        #[track_caller]
212
        fn test(mut data: &[u8], min: usize, max: usize, expected: usize) {
213
            assert_eq!(nat(&mut data, min, max), expected);
214
            assert_eq!(data, &[]);
215
        }
216
        test(&[], 0, 0, 0);
217
        test(&[], 0, 0xffff, 0);
218
        test(&[0], 0, 0xffff, 0);
219
        test(&[0x23], 0, 0xffff, 0x2300);
220
        test(&[0x23, 0x58], 0, 0xffff, 0x2358);
221
        test(&[0x23, 0x58], 0x10000, 0x1ffff, 0x12358);
222
        test(&[0], 0, 1, 0);
223
        test(&[1], 0, 1, 1);
224
        test(&[2], 0, 1, 0);
225
        test(&[128], 0, 255, 128);
226
        test(&[1, 0], 0, 256, 256);
227
    }
228
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc