use core::num::NonZeroUsize;
use qubit_codec::Codec;
use qubit_codec::DecodeFailure;
use qubit_utils::nonzero;
use crate::MiscCodecError;
use crate::hex::hex_digit;
use crate::hex::hex_value;
use crate::hex::invalid_hex_digit;
use crate::misc_error::map_misc_decode_failure_with_consumed;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct HexByteCodec {
uppercase: bool,
}
impl HexByteCodec {
#[must_use]
#[inline]
pub const fn new() -> Self {
Self { uppercase: false }
}
#[must_use]
#[inline]
pub const fn upper() -> Self {
Self { uppercase: true }
}
#[must_use]
#[inline]
pub const fn is_uppercase(self) -> bool {
self.uppercase
}
#[must_use]
#[inline]
pub const fn with_uppercase(mut self, uppercase: bool) -> Self {
self.uppercase = uppercase;
self
}
}
impl Codec for HexByteCodec {
type Value = u8;
type Unit = u8;
type DecodeError = MiscCodecError;
type EncodeError = MiscCodecError;
const MIN_UNITS_PER_VALUE: usize = 2;
const MAX_ENCODE_UNITS_PER_VALUE: usize = 2;
const MAX_DECODE_UNITS_PER_VALUE: usize = 2;
#[inline]
unsafe fn decode(
&mut self,
input: &[u8],
input_index: usize,
) -> Result<(u8, NonZeroUsize), DecodeFailure<Self::DecodeError>> {
debug_assert!(input_index + 2 <= input.len());
let high_char = char::from(input[input_index]);
let low_char = char::from(input[input_index + 1]);
let high = hex_value(high_char)
.ok_or_else(|| invalid_hex_digit(input_index, high_char))
.map_err(|error| map_misc_decode_failure_with_consumed(error, nonzero(2)))?;
let low = hex_value(low_char)
.ok_or_else(|| invalid_hex_digit(input_index + 1, low_char))
.map_err(|error| map_misc_decode_failure_with_consumed(error, nonzero(2)))?;
Ok(((high << 4) | low, nonzero(2)))
}
#[inline]
unsafe fn encode(
&mut self,
value: &u8,
output: &mut [u8],
output_index: usize,
) -> Result<usize, Self::EncodeError> {
debug_assert!(output_index + 2 <= output.len());
output[output_index] = hex_digit(*value >> 4, self.uppercase) as u8;
output[output_index + 1] = hex_digit(*value & 0x0f, self.uppercase) as u8;
Ok(2)
}
}