#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![deny(missing_docs)]
#![deny(unsafe_code)]
#[cfg(test)]
mod tests;
mod time;
mod frame_control;
pub use frame_control::*;
mod aux_sec_header;
pub use aux_sec_header::*;
mod addressing;
pub use addressing::*;
mod ie;
pub use ie::*;
mod repr;
pub use repr::*;
#[derive(Debug, Clone, Copy)]
pub struct Error;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Frame<T: AsRef<[u8]>> {
buffer: T,
}
impl<T: AsRef<[u8]>> Frame<T> {
pub fn new(buffer: T) -> Result<Self> {
let b = Self::new_unchecked(buffer);
if !b.check_len() {
return Err(Error);
}
let fc = b.frame_control();
if fc.security_enabled() {
return Err(Error);
}
if fc.frame_type() == FrameType::Unknown {
return Err(Error);
}
if fc.frame_version() == FrameVersion::Unknown {
return Err(Error);
}
if fc.dst_addressing_mode() == AddressingMode::Unknown {
return Err(Error);
}
if fc.src_addressing_mode() == AddressingMode::Unknown {
return Err(Error);
}
Ok(b)
}
fn check_len(&self) -> bool {
let buffer = self.buffer.as_ref();
if buffer.len() < 2 || buffer.len() > 127 {
return false;
}
let fc = self.frame_control();
if !fc.sequence_number_suppression() && buffer.len() < 3 {
return false;
}
true
}
pub fn new_unchecked(buffer: T) -> Self {
Self { buffer }
}
pub fn frame_control(&self) -> FrameControl<&'_ [u8]> {
FrameControl::new_unchecked(&self.buffer.as_ref()[..2])
}
pub fn sequence_number(&self) -> Option<u8> {
if self.frame_control().sequence_number_suppression() {
None
} else {
Some(self.buffer.as_ref()[2])
}
}
pub fn addressing(&self) -> Option<AddressingFields<&'_ [u8], &'_ [u8]>> {
let fc = self.frame_control();
if matches!(fc.frame_type(), FrameType::Ack)
&& matches!(
fc.frame_version(),
FrameVersion::Ieee802154_2003 | FrameVersion::Ieee802154_2006
)
{
return None;
}
if fc.sequence_number_suppression() {
AddressingFields::new(&self.buffer.as_ref()[2..], fc).ok()
} else {
AddressingFields::new(&self.buffer.as_ref()[3..], fc).ok()
}
}
pub fn auxiliary_security_header(&self) -> Option<AuxiliarySecurityHeader<&'_ [u8]>> {
let fc = self.frame_control();
if fc.security_enabled() {
let mut offset = 2;
offset += !fc.sequence_number_suppression() as usize;
if let Some(af) = self.addressing() {
offset += af.len();
}
Some(AuxiliarySecurityHeader::new(
&self.buffer.as_ref()[offset..],
))
} else {
None
}
}
pub fn information_elements(&self) -> Option<InformationElements<&'_ [u8]>> {
let fc = self.frame_control();
if fc.information_elements_present() {
let mut offset = 2;
offset += !fc.sequence_number_suppression() as usize;
if let Some(af) = self.addressing() {
offset += af.len();
}
Some(InformationElements::new(&self.buffer.as_ref()[offset..]).ok()?)
} else {
None
}
}
}
impl<'f, T: AsRef<[u8]> + ?Sized> Frame<&'f T> {
pub fn payload(&self) -> Option<&'f [u8]> {
let fc = self.frame_control();
let mut offset = 0;
offset += 2;
if !fc.sequence_number_suppression() {
offset += 1;
}
if let Some(af) = self.addressing() {
offset += af.len();
}
if fc.security_enabled() {
offset += self.auxiliary_security_header().unwrap().len();
}
if fc.information_elements_present() {
if let Some(ie) = self.information_elements() {
offset += ie.len();
}
}
if self.buffer.as_ref().len() <= offset {
return None;
}
Some(&self.buffer.as_ref()[offset..])
}
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
pub fn set_frame_control(&mut self, fc: &FrameControlRepr) {
let mut w = FrameControl::new_unchecked(&mut self.buffer.as_mut()[..2]);
w.set_frame_type(fc.frame_type);
w.set_security_enabled(fc.security_enabled);
w.set_frame_pending(fc.frame_pending);
w.set_ack_request(fc.ack_request);
w.set_pan_id_compression(fc.pan_id_compression);
w.set_sequence_number_suppression(fc.sequence_number_suppression);
w.set_information_elements_present(fc.information_elements_present);
w.set_dst_addressing_mode(fc.dst_addressing_mode);
w.set_src_addressing_mode(fc.src_addressing_mode);
w.set_frame_version(fc.frame_version);
}
pub fn frame_control_mut(&mut self) -> FrameControl<&'_ mut [u8]> {
FrameControl::new_unchecked(&mut self.buffer.as_mut()[..2])
}
pub fn set_sequence_number(&mut self, sequence_number: u8) {
let mut w = FrameControl::new_unchecked(&mut self.buffer.as_mut()[..2]);
w.set_sequence_number_suppression(false);
self.buffer.as_mut()[2] = sequence_number;
}
pub fn set_addressing_fields(&mut self, addressing_fields: &AddressingFieldsRepr) {
let start = 2 + (!self.frame_control().sequence_number_suppression() as usize);
let (fc, addressing) = self.buffer.as_mut().split_at_mut(start);
let mut w = AddressingFields::new_unchecked(addressing, FrameControl::new_unchecked(fc));
w.write_fields(addressing_fields);
}
pub fn set_aux_sec_header(&mut self) {
todo!();
}
pub fn set_information_elements(
&mut self,
ie: &InformationElementsRepr,
contains_payload: bool,
) {
let mut offset = 2;
offset += !self.frame_control().sequence_number_suppression() as usize;
if let Some(af) = self.addressing() {
offset += af.len();
}
ie.emit(&mut self.buffer.as_mut()[offset..], contains_payload);
}
pub fn set_payload(&mut self, payload: &[u8]) {
let mut offset = 0;
offset += 2;
if !self.frame_control().sequence_number_suppression() {
offset += 1;
}
if let Some(af) = self.addressing() {
offset += af.len();
}
if self.frame_control().security_enabled() {
offset += self.auxiliary_security_header().unwrap().len();
}
if self.frame_control().information_elements_present() {
offset += self.information_elements().unwrap().len();
}
self.buffer.as_mut()[offset..].copy_from_slice(payload);
}
}
impl<'f, T: AsRef<[u8]> + ?Sized> core::fmt::Display for Frame<&'f T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let fc = self.frame_control();
write!(f, "{}", fc)?;
if !fc.sequence_number_suppression() {
writeln!(f, "Sequence number: {}", self.sequence_number().unwrap())?;
}
if let Some(af) = self.addressing() {
write!(f, "{af}")?;
}
if fc.security_enabled() {
todo!();
}
if let Some(ie) = self.information_elements() {
writeln!(f, "Information Elements")?;
for header_ie in ie.header_information_elements() {
writeln!(f, " {}", header_ie)?;
}
for payload_ie in ie.payload_information_elements() {
writeln!(f, " {}", payload_ie)?;
}
}
if let Some(payload) = self.payload() {
writeln!(f, "Payload")?;
writeln!(f, " {:0x?}", payload)?;
}
Ok(())
}
}