#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub enum Issy {
IscrShort(u16),
IscrLong(u32),
Signalling(u32),
}
#[must_use]
pub fn decode_issy_short(bytes: [u8; 2]) -> Option<Issy> {
if bytes[0] & 0x80 != 0 {
return None;
}
let iscr = ((bytes[0] as u16 & 0x7F) << 8) | bytes[1] as u16;
Some(Issy::IscrShort(iscr))
}
#[must_use]
pub fn decode_issy_long(bytes: [u8; 3]) -> Option<Issy> {
if bytes[0] & 0x80 == 0 {
return None;
}
let payload = ((bytes[0] as u32 & 0x3F) << 16) | (bytes[1] as u32) << 8 | bytes[2] as u32;
if bytes[0] & 0x40 == 0 {
Some(Issy::IscrLong(payload)) } else {
Some(Issy::Signalling(payload)) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn iscr_short_decodes_15_bits() {
assert_eq!(
decode_issy_short([0x7A, 0xBC]),
Some(Issy::IscrShort(0x7ABC))
);
assert_eq!(decode_issy_short([0x00, 0x01]), Some(Issy::IscrShort(1)));
}
#[test]
fn short_rejects_long_prefix() {
assert_eq!(decode_issy_short([0x80, 0x00]), None);
}
#[test]
fn iscr_long_decodes_22_bits() {
assert_eq!(
decode_issy_long([0xBF, 0xFF, 0xFF]),
Some(Issy::IscrLong(0x3FFFFF))
);
assert_eq!(
decode_issy_long([0x80, 0x12, 0x34]),
Some(Issy::IscrLong(0x1234))
);
}
#[test]
fn signalling_decodes_with_11_prefix() {
assert_eq!(
decode_issy_long([0xC0, 0x12, 0x34]),
Some(Issy::Signalling(0x1234))
);
}
#[test]
fn long_rejects_short_prefix() {
assert_eq!(decode_issy_long([0x00, 0x00, 0x00]), None);
}
}