qubit_codec_misc/
hex_byte_codec.rs1use qubit_codec::Codec;
11use qubit_codec::DecodeFailure;
12use qubit_utils::nonzero;
13
14use crate::MiscCodecError;
15use crate::hex_codec::hex_digit;
16use crate::hex_codec::hex_value;
17use crate::hex_codec::invalid_hex_digit;
18use crate::misc_codec_error::map_misc_decode_failure_with_consumed;
19
20#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
42pub struct HexByteCodec {
43 uppercase: bool,
45}
46
47impl HexByteCodec {
48 #[must_use]
50 #[inline]
51 pub const fn new() -> Self {
52 Self { uppercase: false }
53 }
54
55 #[must_use]
57 #[inline]
58 pub const fn upper() -> Self {
59 Self { uppercase: true }
60 }
61
62 #[must_use]
64 #[inline]
65 pub const fn is_uppercase(self) -> bool {
66 self.uppercase
67 }
68
69 #[must_use]
71 #[inline]
72 pub const fn with_uppercase(mut self, uppercase: bool) -> Self {
73 self.uppercase = uppercase;
74 self
75 }
76}
77
78impl Codec for HexByteCodec {
79 type Value = u8;
80 type Unit = u8;
81 type DecodeError = MiscCodecError;
82 type EncodeError = MiscCodecError;
83
84 const MIN_UNITS_PER_VALUE: usize = 2;
85 const MAX_ENCODE_UNITS_PER_VALUE: usize = 2;
86 const MAX_DECODE_UNITS_PER_VALUE: usize = 2;
87
88 #[inline]
93 unsafe fn decode(
94 &mut self,
95 input: &[u8],
96 input_index: usize,
97 ) -> Result<(u8, core::num::NonZeroUsize), DecodeFailure<Self::DecodeError>> {
98 debug_assert!(input_index + 2 <= input.len());
99
100 let high_char = char::from(input[input_index]);
101 let low_char = char::from(input[input_index + 1]);
102 let high = hex_value(high_char)
103 .ok_or_else(|| invalid_hex_digit(input_index, high_char))
104 .map_err(|error| map_misc_decode_failure_with_consumed(error, nonzero(2)))?;
105 let low = hex_value(low_char)
106 .ok_or_else(|| invalid_hex_digit(input_index + 1, low_char))
107 .map_err(|error| map_misc_decode_failure_with_consumed(error, nonzero(2)))?;
108 Ok(((high << 4) | low, nonzero(2)))
109 }
110
111 #[inline]
116 unsafe fn encode(
117 &mut self,
118 value: &u8,
119 output: &mut [u8],
120 output_index: usize,
121 ) -> Result<usize, Self::EncodeError> {
122 debug_assert!(output_index + 2 <= output.len());
123
124 output[output_index] = hex_digit(*value >> 4, self.uppercase) as u8;
125 output[output_index + 1] = hex_digit(*value & 0x0f, self.uppercase) as u8;
126 Ok(2)
127 }
128}