use crc;
use serde::{de, Deserializer, Serializer};
use std::fmt;
const CRC_YUBICO: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
const MODHEX: [char; 16] = [
'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'r', 't', 'u', 'v',
];
pub fn get_crc(bytes: &[u8]) -> u16 {
let mut digest = CRC_YUBICO.digest();
digest.update(bytes);
return digest.finalize();
}
pub fn to_modkex(bytes: &[u8]) -> String {
let mut output = String::with_capacity(bytes.len() * 2);
for byte in bytes {
output.push(MODHEX[(byte >> 4) as usize]);
output.push(MODHEX[(byte & 0xf) as usize]);
}
output
}
pub fn serialize_hex<S>(array: &[u8], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&hex::encode(array))
}
pub fn deserialize_hex<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error>
where
D: Deserializer<'de>,
{
struct StringVisitor<const M: usize>;
impl<'de, const M: usize> de::Visitor<'de> for StringVisitor<M> {
type Value = [u8; M];
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a hex string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let mut output = [0u8; M];
hex::decode_to_slice(v, &mut output).map_err(E::custom)?;
Ok(output)
}
}
deserializer.deserialize_any(StringVisitor::<N>)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crc_check() {
assert_eq!(get_crc(b"123456789"), 0x906e)
}
#[test]
fn test_modhex() {
assert_eq!(to_modkex(&[0xaf, 0x1d, 0xc5]), "lvbtrg")
}
}