use crate::frame_types::*;
#[inline]
fn flag_is_set(data: u8, bit: u8) -> bool {
if bit == 0 {
let mask = 1;
(data & mask) > 0
} else {
let mask = 1 << bit;
(data & mask) > 0
}
}
#[derive(Clone, Debug)]
pub struct FrameControl {
pub protocol_version: FrameProtocolVersion,
pub frame_type: FrameType,
pub frame_subtype: FrameSubType,
pub flags: u8,
}
impl FrameControl {
pub fn to_ds(&self) -> bool {
flag_is_set(self.flags, 0)
}
pub fn from_ds(&self) -> bool {
flag_is_set(self.flags, 1)
}
pub fn more_frag(&self) -> bool {
flag_is_set(self.flags, 2)
}
pub fn retry(&self) -> bool {
flag_is_set(self.flags, 3)
}
pub fn pwr_mgmt(&self) -> bool {
flag_is_set(self.flags, 4)
}
pub fn more_data(&self) -> bool {
flag_is_set(self.flags, 5)
}
#[deprecated(note = "please use `protected` instead")]
pub fn wep(&self) -> bool {
flag_is_set(self.flags, 6)
}
pub fn protected(&self) -> bool {
flag_is_set(self.flags, 6)
}
pub fn order(&self) -> bool {
flag_is_set(self.flags, 7)
}
pub fn encode(&self) -> [u8; 2] {
let protocol_version_bits = self.protocol_version.to_bytes() & 0b11; let frame_type_bits = (self.frame_type.to_bytes() & 0b11) << 2; let frame_subtype_bits = (self.frame_subtype.to_bytes() & 0b1111) << 4;
let first_byte = frame_subtype_bits | frame_type_bits | protocol_version_bits;
let second_byte = self.flags;
[first_byte, second_byte]
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parsers::parse_frame_control;
fn flag_for_bit(bit: u8, frame_control: &FrameControl) -> bool {
match bit {
0 => frame_control.to_ds(),
1 => frame_control.from_ds(),
2 => frame_control.more_frag(),
3 => frame_control.retry(),
4 => frame_control.pwr_mgmt(),
5 => frame_control.more_data(),
6 => frame_control.protected(),
7 => frame_control.order(),
_ => panic!("Unhandled bit {bit}"),
}
}
#[test]
fn test_flags() {
for bit in 0..7 {
let second_byte = 0b0000_0001 << bit;
let bytes = [0b0000_0000, second_byte];
let frame_control = parse_frame_control(&bytes).unwrap().1;
for check_bit in 0..7 {
if bit == check_bit {
assert!(flag_for_bit(check_bit, &frame_control));
} else {
assert!(!flag_for_bit(check_bit, &frame_control));
}
}
}
}
#[test]
fn test_beacon() {
let bytes = [0b1000_0000, 0b0000_0000];
let frame_control = parse_frame_control(&bytes).unwrap().1;
assert!(matches!(frame_control.frame_type, FrameType::Management));
assert!(matches!(frame_control.frame_subtype, FrameSubType::Beacon));
}
}