use crate::binarytext::BinaryText;
use crate::error::BinTxtError;
#[derive(Clone, Debug)]
pub struct Base16 {}
impl Default for Base16 {
fn default() -> Self {
Self::new()
}
}
impl Base16 {
pub fn new() -> Self {
Self {}
}
}
impl BinaryText for Base16 {
fn base(&self) -> usize {
16
}
fn name(&self) -> &str {
"Base16"
}
fn n_bytes_encode(&self) -> usize {
1
}
fn n_bytes_decode(&self) -> usize {
2
}
fn encode_byte(&self, byte: u8) -> Result<u8, BinTxtError> {
const LUT: [char; 16] = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
];
if byte >= 16 {
let msg = format!("Byte {byte} exceeds maximum {}", 16);
return Err(BinTxtError::EncodingErr(msg));
}
Ok(LUT[byte as usize] as u8)
}
fn encode_into_vec(&self, input: &[u8], res: &mut Vec<u8>) -> Result<(), BinTxtError> {
res.clear();
for byte in input {
let pos = byte >> 4;
let b = self.encode_byte(pos)?;
res.push(b);
let pos = byte & 0xF;
let b = self.encode_byte(pos)?;
res.push(b);
}
Ok(())
}
fn decode_byte(&self, byte: u8) -> Result<u8, BinTxtError> {
const LUT: [u8; 128] = [
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255,
255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 255, 255, 255, 255, 255,
];
let b = if byte < 128 { LUT[byte as usize] } else { 255 };
if b < 255 {
Ok(b)
} else {
let errmsg = format!("Invalid byte \"{}\" in Base16 string", byte);
Err(BinTxtError::DecodingErr(errmsg))
}
}
fn decode_into_vec(&self, input: &[u8], res: &mut Vec<u8>) -> Result<(), BinTxtError> {
if !input.len().is_multiple_of(2) {
let errmsg = "Length of input must be a multiple of 2".to_string();
return Err(BinTxtError::DecodingErr(errmsg));
}
res.clear();
if !input.is_empty() {
let start = if &input[0..2] == b"0x" || &input[0..2] == b"0X" {
2
} else {
0
};
for bytes in input[start..].chunks_exact(2) {
let dec = self.decode_byte(bytes[0])?;
let mut val = dec << 4;
let dec = self.decode_byte(bytes[1])?;
val |= dec;
res.push(val);
}
}
Ok(())
}
fn is_decodable(&self, input: &str) -> bool {
if !input.len().is_multiple_of(2) {
return false;
}
for &byte in input.as_bytes() {
match self.decode_byte(byte) {
Ok(_) => {}
Err(_) => {
return false;
}
}
}
true
}
}