const HEX_CHARS: &[u8; 16] = b"0123456789ABCDEF";
#[inline]
pub fn byte2hex(b: u8) -> [u8; 2] { [HEX_CHARS[(b >> 4) as usize & 0x0F], HEX_CHARS[(b & 0x0F) as usize]] }
#[inline]
pub fn int2hex(v: i32) -> [u8; 2] { let mut n = v; if n < 0 { n += 256; } byte2hex((n & 0xFF) as u8) }
#[inline]
pub fn short2hex(v: i16) -> [u8; 4] { [HEX_CHARS[((v >> 12) & 0x0F) as usize], HEX_CHARS[((v >> 8) & 0x0F) as usize], HEX_CHARS[((v >> 4) & 0x0F) as usize], HEX_CHARS[(v & 0x0F) as usize]] }
#[inline]
pub fn num_to_hex8(v: u16) -> [u8; 4] { [HEX_CHARS[((v >> 12) & 0x0F) as usize], HEX_CHARS[((v >> 8) & 0x0F) as usize], HEX_CHARS[((v >> 4) & 0x0F) as usize], HEX_CHARS[(v & 0x0F) as usize]] }
pub fn hex2bytes(s: &str, out: &mut [u8]) -> Option<usize> {
if s.is_empty() { return None; }
let bytes = s.as_bytes(); let mut nibbles = [0u8; 2]; let mut ni = 0usize; let mut oi = 0usize;
for &b in bytes { let v = match b { b' ' | b'\t' => continue, b'0'..=b'9' => b - b'0', b'a'..=b'f' => b - b'a' + 10, b'A'..=b'F' => b - b'A' + 10, _ => return None }; nibbles[ni] = v; ni += 1; if ni == 2 { if oi >= out.len() { return None; } out[oi] = (nibbles[0] << 4) | nibbles[1]; oi += 1; ni = 0; } }
if ni != 0 { return None; } Some(oi)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn helpers() { assert_eq!(byte2hex(0x3A), *b"3A"); assert_eq!(int2hex(-1), *b"FF"); assert_eq!(short2hex(0x3A98), *b"3A98"); assert_eq!(num_to_hex8(0x1234), *b"1234"); }
#[test]
fn hex2bytes_writes_buffer() { let mut buf = [0u8; 16]; assert_eq!(hex2bytes("3A98FF", &mut buf), Some(3)); assert_eq!(&buf[..3], &[0x3A, 0x98, 0xFF]); assert_eq!(hex2bytes("", &mut buf), None); assert_eq!(hex2bytes("GG", &mut buf), None); }
}