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}