use core::mem;
use crate::internal::macros::impl_byte;
use crate::internal::types::IeeeAddress;
impl_byte! {
#[derive(Debug)]
pub struct AuxFrameHeader {
pub security_control: SecurityControl,
pub frame_counter: u32,
#[parse_if = security_control.extended_nonce()]
pub source_address: Option<IeeeAddress>,
#[parse_if = security_control.is_network_key()]
pub key_sequence_numner: Option<u8>,
}
}
impl_byte! {
#[derive(Clone, Copy)]
pub struct SecurityControl(pub u8);
}
impl core::fmt::Debug for SecurityControl {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SecurityControl")
.field("security_level", &self.security_level())
.field("key_identifier", &self.key_identifier())
.field("extended_nonce", &self.extended_nonce())
.finish()
}
}
impl SecurityControl {
pub fn security_level(&self) -> SecurityLevel {
unsafe { mem::transmute(self.0 & 0b111) }
}
pub fn key_identifier(&self) -> KeyIdentifier {
unsafe { mem::transmute((self.0 >> 3) & 0b11) }
}
pub(crate) fn is_network_key(&self) -> bool {
self.key_identifier() == KeyIdentifier::Network
}
pub fn extended_nonce(&self) -> bool {
self.0 >> 5 != 0
}
}
#[repr(u8)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum SecurityLevel {
#[default]
None = 0b000,
Mic32 = 0b001,
Mic64 = 0b010,
Mic128 = 0b011,
Enc = 0b100,
EncMic32 = 0b101,
EncMic64 = 0b110,
EncMic128 = 0b111,
}
impl SecurityLevel {
pub fn mic_length(&self) -> usize {
match self {
Self::EncMic32 | Self::Mic32 => 4,
Self::EncMic64 | Self::Mic64 => 8,
Self::EncMic128 | Self::Mic128 => 16,
Self::None | Self::Enc => 0,
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum KeyIdentifier {
Data = 0b00,
Network = 0b01,
KeyTransport = 0b10,
KeyLoad = 0b11,
}