use super::*;
use crate::{Address, AddressingMode, FrameType, FrameVersion};
use crate::{Error, Result};
pub struct Beacon;
pub struct EnhancedBeacon;
pub struct Ack;
pub struct Data;
pub struct FrameBuilder<'p, T> {
frame: FrameRepr<'p>,
r#type: core::marker::PhantomData<T>,
}
impl<'p> FrameBuilder<'p, Ack> {
pub fn new_imm_ack(sequence_number: u8) -> Self {
Self {
frame: FrameRepr {
frame_control: FrameControlRepr {
frame_type: FrameType::Ack,
security_enabled: false,
frame_pending: false,
ack_request: false,
pan_id_compression: false,
sequence_number_suppression: false,
information_elements_present: false,
dst_addressing_mode: AddressingMode::Absent,
src_addressing_mode: AddressingMode::Absent,
frame_version: FrameVersion::Ieee802154_2006,
},
sequence_number: Some(sequence_number),
addressing_fields: None,
information_elements: None,
payload: None,
},
r#type: Default::default(),
}
}
pub fn new_ack() -> Self {
Self {
frame: FrameRepr {
frame_control: FrameControlRepr {
frame_type: FrameType::Ack,
security_enabled: false,
frame_pending: false,
ack_request: false,
pan_id_compression: false,
sequence_number_suppression: true,
information_elements_present: false,
dst_addressing_mode: AddressingMode::Absent,
src_addressing_mode: AddressingMode::Absent,
frame_version: FrameVersion::Ieee802154_2020,
},
sequence_number: None,
addressing_fields: None,
information_elements: None,
payload: None,
},
r#type: Default::default(),
}
}
}
impl<'p> FrameBuilder<'p, Beacon> {
pub fn new_beacon() -> Self {
Self {
frame: FrameRepr {
frame_control: FrameControlRepr {
frame_type: FrameType::Beacon,
security_enabled: false,
frame_pending: false,
ack_request: false,
pan_id_compression: false,
sequence_number_suppression: true,
information_elements_present: false,
dst_addressing_mode: AddressingMode::Absent,
src_addressing_mode: AddressingMode::Absent,
frame_version: FrameVersion::Ieee802154_2006,
},
sequence_number: None,
addressing_fields: None,
information_elements: None,
payload: None,
},
r#type: core::marker::PhantomData,
}
}
}
impl<'p> FrameBuilder<'p, EnhancedBeacon> {
pub fn new_enhanced_beacon() -> Self {
Self {
frame: FrameRepr {
frame_control: FrameControlRepr {
frame_type: FrameType::Beacon,
security_enabled: false,
frame_pending: false,
ack_request: false,
pan_id_compression: false,
sequence_number_suppression: true,
information_elements_present: false,
dst_addressing_mode: AddressingMode::Absent,
src_addressing_mode: AddressingMode::Absent,
frame_version: FrameVersion::Ieee802154_2020,
},
sequence_number: None,
addressing_fields: None,
information_elements: None,
payload: None,
},
r#type: core::marker::PhantomData,
}
}
}
impl<'p> FrameBuilder<'p, Data> {
pub fn new_data(payload: &'p [u8]) -> Self {
Self {
frame: FrameRepr {
frame_control: FrameControlRepr {
frame_type: FrameType::Data,
security_enabled: false,
frame_pending: false,
ack_request: false,
pan_id_compression: false,
sequence_number_suppression: true,
information_elements_present: false,
dst_addressing_mode: AddressingMode::Absent,
src_addressing_mode: AddressingMode::Absent,
frame_version: FrameVersion::Ieee802154_2006,
},
sequence_number: None,
addressing_fields: None,
information_elements: None,
payload: Some(payload),
},
r#type: core::marker::PhantomData,
}
}
}
impl<'p, T> FrameBuilder<'p, T> {
pub fn set_sequence_number(mut self, sequence_number: u8) -> Self {
self.frame.sequence_number = Some(sequence_number);
self.frame.frame_control.sequence_number_suppression = false;
self
}
pub fn set_dst_pan_id(mut self, pan_id: u16) -> Self {
self.frame
.addressing_fields
.get_or_insert_with(AddressingFieldsRepr::default)
.dst_pan_id = Some(pan_id);
self
}
pub fn set_src_pan_id(mut self, pan_id: u16) -> Self {
self.frame
.addressing_fields
.get_or_insert_with(AddressingFieldsRepr::default)
.src_pan_id = Some(pan_id);
self
}
pub fn set_dst_address(mut self, address: Address) -> Self {
self.frame.frame_control.dst_addressing_mode = address.into();
self.frame
.addressing_fields
.get_or_insert_with(AddressingFieldsRepr::default)
.dst_address = Some(address);
self
}
pub fn set_src_address(mut self, address: Address) -> Self {
self.frame.frame_control.src_addressing_mode = address.into();
self.frame
.addressing_fields
.get_or_insert_with(AddressingFieldsRepr::default)
.src_address = Some(address);
self
}
pub fn add_header_information_element(mut self, ie: HeaderInformationElementRepr) -> Self {
self.frame.frame_control.information_elements_present = true;
self.frame
.information_elements
.get_or_insert_with(InformationElementsRepr::default)
.header_information_elements
.push(ie)
.unwrap();
self.frame.frame_control.frame_version = FrameVersion::Ieee802154_2020;
self
}
pub fn add_payload_information_element(mut self, ie: PayloadInformationElementRepr) -> Self {
self.frame.frame_control.information_elements_present = true;
self.frame
.information_elements
.get_or_insert_with(InformationElementsRepr::default)
.payload_information_elements
.push(ie)
.unwrap();
self.frame.frame_control.frame_version = FrameVersion::Ieee802154_2020;
self
}
pub fn set_payload(mut self, payload: &'p [u8]) -> Self {
self.frame.payload = Some(payload);
self
}
pub fn finalize(mut self) -> Result<FrameRepr<'p>> {
if self.frame.frame_control.frame_version == FrameVersion::Ieee802154_2020 {
let Some(addr) = self.frame.addressing_fields.as_mut() else {
return Err(Error);
};
self.frame.frame_control.pan_id_compression = match (
addr.dst_address,
addr.src_address,
addr.dst_pan_id,
addr.src_pan_id,
) {
(None, None, None, None) => false,
(None, None, Some(_), None) => true,
(Some(_), None, Some(_), None) => false,
(None, Some(_), None, Some(_)) => false,
(None, Some(_), None, None) => true,
(Some(Address::Extended(_)), Some(Address::Extended(_)), Some(_), None) => false,
(Some(Address::Extended(_)), Some(Address::Extended(_)), None, None) => true,
(Some(Address::Short(_)), Some(Address::Short(_)), Some(dst), Some(src)) => {
if dst == src {
addr.src_pan_id = None;
}
dst == src
}
(Some(Address::Short(_)), Some(Address::Extended(_)), Some(dst), Some(src)) => {
if dst == src {
addr.src_pan_id = None;
}
dst == src
}
(Some(Address::Extended(_)), Some(Address::Short(_)), Some(dst), Some(src)) => {
if dst == src {
addr.src_pan_id = None;
}
dst == src
}
(Some(Address::Short(_)), Some(Address::Extended(_)), Some(_), None) => true,
(Some(Address::Extended(_)), Some(Address::Short(_)), Some(_), None) => true,
(Some(Address::Short(_)), Some(Address::Short(_)), Some(_), None) => true,
_ => return Err(Error),
};
} else {
if matches!(self.frame.frame_control.frame_type, FrameType::Ack) {
if self.frame.sequence_number.is_none() {
return Err(Error);
}
self.frame.addressing_fields = None;
return Ok(self.frame);
}
let Some(addr) = self.frame.addressing_fields.as_mut() else {
return Err(Error);
};
match (
addr.dst_address,
addr.src_address,
addr.dst_pan_id,
addr.src_pan_id,
) {
(Some(_), Some(_), Some(dst_pan_id), Some(src_pan_id)) => {
if dst_pan_id == src_pan_id {
self.frame.frame_control.pan_id_compression = true;
addr.src_pan_id = None;
}
}
(Some(_), None, Some(_), _) => {
self.frame.frame_control.pan_id_compression = false;
addr.src_pan_id = None;
}
(None, Some(_), _, Some(_)) => {
self.frame.frame_control.pan_id_compression = false;
addr.dst_pan_id = None;
}
_ => return Err(Error),
}
}
Ok(self.frame)
}
}