use super::util::{set_flag, set_subfield};
use super::*;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct Dot11QosControl {
bits: u16,
}
impl Dot11QosControl {
pub const fn new() -> Self {
Self { bits: 0 }
}
pub const fn from_bits(bits: u16) -> Self {
Self { bits }
}
pub const fn from_le_bytes(bytes: [u8; DOT11_QOS_CONTROL_LEN]) -> Self {
Self {
bits: (bytes[0] as u16) | ((bytes[1] as u16) << 8),
}
}
pub fn decode(bytes: impl AsRef<[u8]>) -> crate::Result<Self> {
let bytes = bytes.as_ref();
if bytes.len() < DOT11_QOS_CONTROL_LEN {
return Err(crate::CrafterError::buffer_too_short(
"dot11.qos_control",
DOT11_QOS_CONTROL_LEN,
bytes.len(),
));
}
Ok(Self::from_le_bytes([bytes[0], bytes[1]]))
}
pub const fn bits(&self) -> u16 {
self.bits
}
pub const fn raw(mut self, bits: u16) -> Self {
self.bits = bits;
self
}
pub const fn to_le_bytes(self) -> [u8; DOT11_QOS_CONTROL_LEN] {
[(self.bits & 0x00ff) as u8, (self.bits >> 8) as u8]
}
pub const fn compile(self) -> [u8; DOT11_QOS_CONTROL_LEN] {
self.to_le_bytes()
}
pub const fn tid(&self) -> u8 {
((self.bits & DOT11_QOS_TID_MASK) >> DOT11_QOS_TID_SHIFT) as u8
}
pub const fn eosp(&self) -> bool {
self.has_flag(DOT11_QOS_EOSP)
}
pub const fn ack_policy(&self) -> u8 {
((self.bits & DOT11_QOS_ACK_POLICY_MASK) >> DOT11_QOS_ACK_POLICY_SHIFT) as u8
}
pub const fn a_msdu_present(&self) -> bool {
self.has_flag(DOT11_QOS_A_MSDU_PRESENT)
}
pub const fn txop_queue_size(&self) -> u8 {
((self.bits & DOT11_QOS_TXOP_QUEUE_SIZE_MASK) >> DOT11_QOS_TXOP_QUEUE_SIZE_SHIFT) as u8
}
pub const fn tid_set(mut self, tid: u8) -> Self {
self.bits = set_subfield(self.bits, DOT11_QOS_TID_MASK, DOT11_QOS_TID_SHIFT, tid);
self
}
pub const fn with_tid(self, tid: u8) -> Self {
self.tid_set(tid)
}
pub const fn eosp_set(mut self, enabled: bool) -> Self {
self.bits = set_flag(self.bits, DOT11_QOS_EOSP, enabled);
self
}
pub const fn with_eosp(self, enabled: bool) -> Self {
self.eosp_set(enabled)
}
pub const fn ack_policy_set(mut self, ack_policy: u8) -> Self {
self.bits = set_subfield(
self.bits,
DOT11_QOS_ACK_POLICY_MASK,
DOT11_QOS_ACK_POLICY_SHIFT,
ack_policy,
);
self
}
pub const fn with_ack_policy(self, ack_policy: u8) -> Self {
self.ack_policy_set(ack_policy)
}
pub const fn a_msdu_present_set(mut self, enabled: bool) -> Self {
self.bits = set_flag(self.bits, DOT11_QOS_A_MSDU_PRESENT, enabled);
self
}
pub const fn with_a_msdu_present(self, enabled: bool) -> Self {
self.a_msdu_present_set(enabled)
}
pub const fn txop_queue_size_set(mut self, value: u8) -> Self {
self.bits = set_subfield(
self.bits,
DOT11_QOS_TXOP_QUEUE_SIZE_MASK,
DOT11_QOS_TXOP_QUEUE_SIZE_SHIFT,
value,
);
self
}
pub const fn with_txop_queue_size(self, value: u8) -> Self {
self.txop_queue_size_set(value)
}
const fn has_flag(&self, flag: u16) -> bool {
self.bits & flag != 0
}
}
impl From<u16> for Dot11QosControl {
fn from(value: u16) -> Self {
Self::from_bits(value)
}
}
impl From<Dot11QosControl> for u16 {
fn from(value: Dot11QosControl) -> Self {
value.bits()
}
}