1use super::error::NetbatError;
2
3pub fn decode_hex(input: &[u8], max_input_bytes: usize) -> Result<Vec<u8>, NetbatError> {
9 if !input.len().is_multiple_of(2) {
10 return Err(NetbatError::MalformedRequest {
11 reason: "hex input has odd length",
12 });
13 }
14 if input.len() / 2 > max_input_bytes {
15 return Err(NetbatError::InputTooLarge {
16 max: max_input_bytes,
17 });
18 }
19
20 let mut output = Vec::with_capacity(input.len() / 2);
21 for pair in input.chunks_exact(2) {
22 let high = hex_value(pair[0])?;
23 let low = hex_value(pair[1])?;
24 output.push((high << 4) | low);
25 }
26 Ok(output)
27}
28
29fn hex_value(byte: u8) -> Result<u8, NetbatError> {
30 match byte {
31 b'0'..=b'9' => Ok(byte - b'0'),
32 b'a'..=b'f' => Ok(byte - b'a' + 10),
33 b'A'..=b'F' => Ok(byte - b'A' + 10),
34 _ => Err(NetbatError::MalformedRequest {
35 reason: "input is not hex",
36 }),
37 }
38}
39
40pub fn encode_hex_into(bytes: &[u8], output: &mut Vec<u8>) {
42 const HEX: &[u8; 16] = b"0123456789abcdef";
43 output.reserve(bytes.len() * 2);
44 for byte in bytes {
45 output.push(HEX[(byte >> 4) as usize]);
46 output.push(HEX[(byte & 0x0f) as usize]);
47 }
48}
49
50#[must_use]
53pub fn encode_hex(bytes: &[u8]) -> Vec<u8> {
54 let mut output = Vec::with_capacity(bytes.len() * 2);
55 encode_hex_into(bytes, &mut output);
56 output
57}
58
59#[must_use]
67pub fn encode_hex_str(bytes: &[u8]) -> String {
68 let buf = encode_hex(bytes);
69 String::from_utf8(buf).expect("lowercase-hex encoder produces ASCII")
72}
73
74pub fn decode_hex_str(input: &str) -> Result<Vec<u8>, NetbatError> {
85 decode_hex(input.as_bytes(), usize::MAX)
86}