#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Class {
cla: u8,
range: Range,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SecureMessaging {
None = 0,
Proprietary = 1,
Standard = 2,
Authenticated = 3,
Unknown,
}
impl SecureMessaging {
pub fn none(&self) -> bool {
*self == SecureMessaging::None
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Chain {
LastOrOnly,
NotTheLast,
Unknown,
}
impl Chain {
#[inline]
pub fn last_or_only(&self) -> bool {
*self == Chain::LastOrOnly
}
#[inline]
pub fn not_the_last(&self) -> bool {
*self == Chain::NotTheLast
}
}
impl Class {
#[inline]
pub fn into_inner(self) -> u8 {
self.cla
}
#[inline]
pub fn range(&self) -> Range {
self.range
}
#[inline]
pub fn secure_messaging(&self) -> SecureMessaging {
match self.range {
Range::Interindustry(which) => match which {
Interindustry::First => {
match (self.cla >> 2) & 0b11 {
0b00 => SecureMessaging::None,
0b01 => SecureMessaging::Proprietary,
0b10 => SecureMessaging::Standard,
0b11 => SecureMessaging::Authenticated,
_ => unreachable!(),
}
},
Interindustry::Further => {
match (self.cla >> 5) != 0 {
true => SecureMessaging::Standard,
false => SecureMessaging::None,
}
}
Interindustry::Reserved => SecureMessaging::Unknown,
}
_ => SecureMessaging::Unknown,
}
}
#[inline]
pub fn chain(&self) -> Chain {
if self.cla & (1 << 4) != 0 {
Chain::NotTheLast
} else {
Chain::LastOrOnly
}
}
#[inline]
pub fn channel(&self) -> Option<u8> {
Some(match self.range() {
Range::Interindustry(Interindustry::First) => {
self.cla & 0b11
}
Range::Interindustry(Interindustry::Further) => {
4 + self.cla & 0b111
}
_ => return None
})
}
}
impl core::convert::TryFrom<u8> for Class {
type Error = InvalidClass;
#[inline]
fn try_from(cla: u8) -> Result<Self, Self::Error> {
let range = Range::try_from(cla)?;
Ok(Self { cla, range })
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Range {
Interindustry(Interindustry),
Proprietary,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Interindustry {
First,
Further,
Reserved,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct InvalidClass {}
impl core::convert::TryFrom<u8> for Range {
type Error = InvalidClass;
#[inline]
fn try_from(cla: u8) -> Result<Self, Self::Error> {
if cla == 0xff {
return Err(InvalidClass {})
}
let range = match cla >> 5 {
0b000 => Range::Interindustry(Interindustry::First),
0b010 | 0b011 => Range::Interindustry(Interindustry::Further),
0b001 => Range::Interindustry(Interindustry::Reserved),
_ => Range::Proprietary,
};
Ok(range)
}
}