/rust/registry/src/index.crates.io-1949cf8c6b5b557f/base16ct-0.2.0/src/lower.rs
Line | Count | Source |
1 | | use crate::{decode_inner, encoded_len, Error}; |
2 | | #[cfg(feature = "alloc")] |
3 | | use crate::{decoded_len, String, Vec}; |
4 | | |
5 | | /// Decode a lower Base16 (hex) string into the provided destination buffer. |
6 | 0 | pub fn decode(src: impl AsRef<[u8]>, dst: &mut [u8]) -> Result<&[u8], Error> { |
7 | 0 | decode_inner(src.as_ref(), dst, decode_nibble) |
8 | 0 | } |
9 | | |
10 | | /// Decode a lower Base16 (hex) string into a byte vector. |
11 | | #[cfg(feature = "alloc")] |
12 | 0 | pub fn decode_vec(input: impl AsRef<[u8]>) -> Result<Vec<u8>, Error> { |
13 | 0 | let mut output = vec![0u8; decoded_len(input.as_ref())?]; |
14 | 0 | decode(input, &mut output)?; |
15 | 0 | Ok(output) |
16 | 0 | } |
17 | | |
18 | | /// Encode the input byte slice as lower Base16. |
19 | | /// |
20 | | /// Writes the result into the provided destination slice, returning an |
21 | | /// ASCII-encoded lower Base16 (hex) string value. |
22 | 0 | pub fn encode<'a>(src: &[u8], dst: &'a mut [u8]) -> Result<&'a [u8], Error> { |
23 | 0 | let dst = dst |
24 | 0 | .get_mut(..encoded_len(src)) |
25 | 0 | .ok_or(Error::InvalidLength)?; |
26 | 0 | for (src, dst) in src.iter().zip(dst.chunks_exact_mut(2)) { |
27 | 0 | dst[0] = encode_nibble(src >> 4); |
28 | 0 | dst[1] = encode_nibble(src & 0x0f); |
29 | 0 | } |
30 | 0 | Ok(dst) |
31 | 0 | } |
32 | | |
33 | | /// Encode input byte slice into a [`&str`] containing lower Base16 (hex). |
34 | 0 | pub fn encode_str<'a>(src: &[u8], dst: &'a mut [u8]) -> Result<&'a str, Error> { |
35 | 0 | encode(src, dst).map(|r| unsafe { core::str::from_utf8_unchecked(r) }) |
36 | 0 | } |
37 | | |
38 | | /// Encode input byte slice into a [`String`] containing lower Base16 (hex). |
39 | | /// |
40 | | /// # Panics |
41 | | /// If `input` length is greater than `usize::MAX/2`. |
42 | | #[cfg(feature = "alloc")] |
43 | 0 | pub fn encode_string(input: &[u8]) -> String { |
44 | 0 | let elen = encoded_len(input); |
45 | 0 | let mut dst = vec![0u8; elen]; |
46 | 0 | let res = encode(input, &mut dst).expect("dst length is correct"); |
47 | | |
48 | 0 | debug_assert_eq!(elen, res.len()); |
49 | 0 | unsafe { String::from_utf8_unchecked(dst) } |
50 | 0 | } |
51 | | |
52 | | /// Decode a single nibble of lower hex |
53 | | #[inline(always)] |
54 | 0 | fn decode_nibble(src: u8) -> u16 { |
55 | | // 0-9 0x30-0x39 |
56 | | // A-F 0x41-0x46 or a-f 0x61-0x66 |
57 | 0 | let byte = src as i16; |
58 | 0 | let mut ret: i16 = -1; |
59 | | |
60 | | // 0-9 0x30-0x39 |
61 | | // if (byte > 0x2f && byte < 0x3a) ret += byte - 0x30 + 1; // -47 |
62 | 0 | ret += (((0x2fi16 - byte) & (byte - 0x3a)) >> 8) & (byte - 47); |
63 | | // a-f 0x61-0x66 |
64 | | // if (byte > 0x60 && byte < 0x67) ret += byte - 0x61 + 10 + 1; // -86 |
65 | 0 | ret += (((0x60i16 - byte) & (byte - 0x67)) >> 8) & (byte - 86); |
66 | | |
67 | 0 | ret as u16 |
68 | 0 | } |
69 | | |
70 | | /// Encode a single nibble of hex |
71 | | #[inline(always)] |
72 | 0 | fn encode_nibble(src: u8) -> u8 { |
73 | 0 | let mut ret = src as i16 + 0x30; |
74 | | // 0-9 0x30-0x39 |
75 | | // a-f 0x61-0x66 |
76 | 0 | ret += ((0x39i16 - ret) >> 8) & (0x61i16 - 0x3a); |
77 | 0 | ret as u8 |
78 | 0 | } |