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)]
27pub struct HexByteCodec {
28 uppercase: bool,
29}
30
31impl HexByteCodec {
32 #[must_use]
34 #[inline]
35 pub const fn new() -> Self {
36 Self { uppercase: false }
37 }
38
39 #[must_use]
41 #[inline]
42 pub const fn upper() -> Self {
43 Self { uppercase: true }
44 }
45
46 #[must_use]
48 #[inline]
49 pub const fn with_uppercase(mut self, uppercase: bool) -> Self {
50 self.uppercase = uppercase;
51 self
52 }
53
54 #[must_use]
56 #[inline]
57 pub const fn is_uppercase(self) -> bool {
58 self.uppercase
59 }
60}
61
62impl Codec for HexByteCodec {
63 type Value = u8;
64 type Unit = u8;
65 type DecodeError = MiscCodecError;
66 type EncodeError = MiscCodecError;
67
68 const MIN_UNITS_PER_VALUE: usize = 2;
69 const MAX_ENCODE_UNITS_PER_VALUE: usize = 2;
70 const MAX_DECODE_UNITS_PER_VALUE: usize = 2;
71
72 #[inline]
77 unsafe fn decode(
78 &mut self,
79 input: &[u8],
80 input_index: usize,
81 ) -> Result<(u8, core::num::NonZeroUsize), DecodeFailure<Self::DecodeError>>
82 {
83 debug_assert!(input_index + 2 <= input.len());
84
85 let high_char = char::from(input[input_index]);
86 let low_char = char::from(input[input_index + 1]);
87 let high = hex_value(high_char)
88 .ok_or_else(|| invalid_hex_digit(input_index, high_char))
89 .map_err(|error| {
90 map_misc_decode_failure_with_consumed(error, nonzero(2))
91 })?;
92 let low = hex_value(low_char)
93 .ok_or_else(|| invalid_hex_digit(input_index + 1, low_char))
94 .map_err(|error| {
95 map_misc_decode_failure_with_consumed(error, nonzero(2))
96 })?;
97 Ok(((high << 4) | low, nonzero(2)))
98 }
99
100 #[inline]
105 unsafe fn encode(
106 &mut self,
107 value: &u8,
108 output: &mut [u8],
109 output_index: usize,
110 ) -> Result<usize, Self::EncodeError> {
111 debug_assert!(output_index + 2 <= output.len());
112
113 output[output_index] = hex_digit(*value >> 4, self.uppercase) as u8;
114 output[output_index + 1] =
115 hex_digit(*value & 0x0f, self.uppercase) as u8;
116 Ok(2)
117 }
118}