wiwi/encoding/hex/encode.rs
1//! Internal encoding implementations
2
3use super::UnsafeBufWriteGuard;
4
5/// Length of encoding table (not actually used in encoding/decoding data)
6pub const TABLE_ENCODER_LEN: usize = 16;
7
8/// Encoding table of lowercased characters, length 16, mapping a value from 0-15
9/// to a hex byte (lower letters)
10///
11/// Note: this table is not actually used in the encoding/decoding implementation
12pub static TABLE_ENCODER_LOWER: [u8; TABLE_ENCODER_LEN] = *b"0123456789abcdef";
13
14/// Encoding table of uppercased characters, length 16, mapping a value from 0-15
15/// to a hex byte (upper letters)
16///
17/// Note: this table is not actually used in the encoding/decoding implementation
18pub static TABLE_ENCODER_UPPER: [u8; TABLE_ENCODER_LEN] = *b"0123456789ABCDEF";
19
20/// Reads `rounds` bytes from `bytes_ptr`, encoding them into 2 hex chars
21/// per byte, then writes the output into `dest`
22///
23/// # SAFETY
24///
25/// - `bytes_ptr` must be valid for `num_rounds` bytes of reads
26/// - `dest` must have enough capacity to write `num_rounds * 2` bytes into
27pub unsafe fn generic<const UPPER: bool>(
28 mut bytes_ptr: *const u8,
29 dest: &mut UnsafeBufWriteGuard,
30 rounds: usize
31) {
32 let char_a = if UPPER { b'A' } else { b'a' } - 10;
33 let char_0 = b'0';
34
35 for _ in 0..rounds {
36 // SAFETY: we loop `num_rounds` times only, reading a byte each time,
37 // and caller promises that `bytes_ptr` is valid to read for at least
38 // that many bytes
39 let byte = unsafe { *bytes_ptr };
40
41 // SAFETY: same invariant as above. It's sound to have the pointer pointing
42 // to the end of the memory section (as long as it isn't dereferenced)
43 bytes_ptr = unsafe { bytes_ptr.add(1) };
44
45 let char1 = byte >> 4;
46 let char2 = byte & 0xf;
47
48 let chars = [
49 if char1 > 9 { char_a } else { char_0 } + char1,
50 if char2 > 9 { char_a } else { char_0 } + char2
51 ];
52
53 // SAFETY: caller guarantees `dest` is writeable to for at least
54 // `num_rounds * 2` bytes, so we can write 2 bytes every iteration
55 unsafe { dest.write_bytes_const::<2>(chars.as_ptr()) }
56 }
57}