pub (crate) fn format_hex_bytes(bytes: &[u8]) -> String { bytes.chunks(2) .map(|chunk| chunk.iter().map(|b| format!("{:02X}", b)).collect::()) .collect::>() .join(" ") } pub (crate) fn parse_access_code(code: &String) -> Option<[u8; 10]> { let matrix_code = format!("{:0>20}", code.replace(" ", "")); let mut bytes: [u8; 10] = [0; 10]; for i in 0..bytes.len() { let slice_str = &matrix_code[i*2..i*2+2]; let slice_val = u8::from_str_radix(slice_str, 16).ok()?; bytes[i] = slice_val; } Some(bytes) } pub (crate) fn parse_idm_hex(idm_hex: &String) -> Option<[u8; 8]> { if idm_hex.len() > 16 || !idm_hex.chars().all(|c| c.is_ascii_hexdigit()) { return None; } let padded_idm = format!("{:0>16}", idm_hex); let mut idm_bytes: [u8; 8] = [0; 8]; for i in 0..idm_bytes.len() { let slice_str = &padded_idm[i*2..i*2+2]; let slice_val = u8::from_str_radix(slice_str, 16).ok()?; idm_bytes[i] = slice_val; } Some(idm_bytes) } pub (crate) fn is_valid_access_code(code: &String) -> bool { if code.len() > 20 { return false; } let cleaned_code: String = code.chars().filter(|c| !c.is_whitespace()).collect(); if cleaned_code.len() != 20 { return false; } let mut seen_non_zero = false; let is_all_digits = cleaned_code.chars().all(|c| { if c != '0' { seen_non_zero = true; } c.is_ascii_digit() }); is_all_digits && seen_non_zero }