use le_stream::{FromLeStream, ToLeStream};
pub use self::ack_fmt::AckFmt;
use crate::{Control, Extended, FrameType};
mod ack_fmt;
#[derive(Clone, Debug, Eq, PartialEq, Hash, ToLeStream)]
pub struct Frame {
control: Control,
fmt: Option<AckFmt>, counter: u8,
extended: Option<Extended>,
}
impl Frame {
#[expect(unsafe_code)]
#[must_use]
pub const unsafe fn new_unchecked(
control: Control,
fmt: Option<AckFmt>,
counter: u8,
extended: Option<Extended>,
) -> Self {
Self {
control,
fmt,
counter,
extended,
}
}
#[must_use]
pub fn new(counter: u8, fmt: Option<AckFmt>, extended: Option<Extended>) -> Self {
let mut control = Control::empty();
control.set_frame_type(FrameType::Acknowledgment);
if fmt.is_none() {
control.insert(Control::ACK_FORMAT);
}
if extended.is_some() {
control.insert(Control::EXTENDED_HEADER);
}
Self {
control,
fmt,
counter,
extended,
}
}
#[must_use]
pub const fn control(&self) -> Control {
self.control
}
#[must_use]
pub const fn fmt(&self) -> Option<AckFmt> {
self.fmt
}
#[must_use]
pub const fn counter(&self) -> u8 {
self.counter
}
#[must_use]
pub const fn extended(&self) -> Option<Extended> {
self.extended
}
}
impl FromLeStream for Frame {
fn from_le_stream<T>(mut bytes: T) -> Option<Self>
where
T: Iterator<Item = u8>,
{
let control = Control::from_le_stream(&mut bytes)?;
let fmt = if control.contains(Control::ACK_FORMAT) {
None
} else {
Some(AckFmt::from_le_stream(&mut bytes)?)
};
let counter = u8::from_le_stream(&mut bytes)?;
let extended = control.deserialize_extended_header(&mut bytes).ok()?;
Some(Self {
control,
fmt,
counter,
extended,
})
}
}