nandi/rustnimpublic Fork 0
ff34e1b3229df6e21b0c5d77053bb9b7364db5cd
Commits
Clone
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

022-base16ct-decode.rs · 89 lines · 2.3 KBRust Blame HistoryRaw
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 18h ago1// Milestone 1, as far as it currently reaches.
2//
3// `Error`, `decoded_len` and `decode_nibble` are base16ct 1.0.0 verbatim.
4// `decode_into` is NOT: base16ct writes that loop as
5// for (src, dst) in src.chunks_exact(2).zip(dst.iter_mut())
6// and `chunks_exact`/`zip`/`iter_mut` are not implemented yet, so the loop is
7// rewritten with indexing. The arithmetic under test -- the constant-time
8// nibble decode, its i16 wrapping and arithmetic shift, and the `err` accumulator
9// -- is unchanged, and that is the part the other transpiler could not represent.
10
11#[derive(Clone, Copy, Eq, PartialEq, Debug)]
12pub enum Error {
13 InvalidEncoding,
14 InvalidLength,
15}
16
17pub type Result<T> = core::result::Result<T, Error>;
18
19pub fn decoded_len(bytes: &[u8]) -> Result<usize> {
20 if bytes.len() & 1 == 0 {
21 Ok(bytes.len() / 2)
22 } else {
23 Err(Error::InvalidLength)
24 }
25}
26
27fn decode_nibble(src: u8) -> u16 {
28 let byte = src as i16;
29 let mut ret: i16 = -1;
30
31 ret += (((0x2fi16 - byte) & (byte - 0x3a)) >> 8) & (byte - 47);
32 ret += (((0x40i16 - byte) & (byte - 0x47)) >> 8) & (byte - 54);
33 ret += (((0x60i16 - byte) & (byte - 0x67)) >> 8) & (byte - 86);
34
35 ret as u16
36}
37
38fn decode_into(src: &[u8], dst: &mut [u8]) -> Result<usize> {
39 let n: usize = decoded_len(src)?;
40 if dst.len() < n {
41 return Err(Error::InvalidLength);
42 }
43
44 let mut err: u16 = 0;
45 let mut i: usize = 0;
46 while i < n {
47 let byte = (decode_nibble(src[i * 2]) << 4) | decode_nibble(src[i * 2 + 1]);
48 err |= byte >> 8;
49 dst[i] = byte as u8;
50 i += 1;
51 }
52
53 match err {
54 0 => Ok(n),
55 _ => Err(Error::InvalidEncoding),
56 }
57}
58
59fn show(hex: &[u8]) {
60 let mut buf: Vec<u8> = vec![0u8; 16];
61 match decode_into(hex, &mut buf) {
62 Ok(n) => {
63 let mut i: usize = 0;
64 while i < n {
65 print!("{:02x}", buf[i]);
66 i += 1;
67 }
68 println!(" ({} bytes)", n);
69 }
70 Err(e) => println!("error {:?}", e),
71 }
72}
73
74fn main() {
75 show(b"abcd1234");
76 show(b"ABCD1234");
77 show(b"abCD1234");
78 show(b"00ff7f80");
79 show(b"abc");
80 show(b"zzzz");
81 show(b"");
82
83 let mut c: u8 = 0;
84 while c < 128 {
85 print!("{} ", decode_nibble(c));
86 c += 1;
87 }
88 println!("");
89}