wlan_common/mac/ctrl/
mod.rs
1use super::{CtrlFrame, CtrlSubtype};
6use zerocopy::{Ref, SplitByteSlice};
7
8mod fields;
9
10pub use fields::*;
11
12#[derive(Debug)]
13pub enum CtrlBody<B: SplitByteSlice> {
14 PsPoll { ps_poll: Ref<B, PsPoll> },
15 Unsupported { subtype: CtrlSubtype },
16}
17
18impl<B: SplitByteSlice> CtrlBody<B> {
19 pub fn parse(subtype: CtrlSubtype, bytes: B) -> Option<Self> {
20 match subtype {
21 CtrlSubtype::PS_POLL => {
22 let (ps_poll, _) = Ref::from_prefix(bytes).ok()?;
23 Some(CtrlBody::PsPoll { ps_poll })
24 }
25 subtype => Some(CtrlBody::Unsupported { subtype }),
26 }
27 }
28}
29
30impl<B> TryFrom<CtrlFrame<B>> for CtrlBody<B>
31where
32 B: SplitByteSlice,
33{
34 type Error = ();
35
36 fn try_from(ctrl_frame: CtrlFrame<B>) -> Result<Self, Self::Error> {
37 CtrlBody::parse(ctrl_frame.ctrl_subtype(), ctrl_frame.body).ok_or(())
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44 use crate::assert_variant;
45 use ieee80211::{Bssid, MacAddr};
46
47 #[test]
48 fn parse_ps_poll_frame() {
49 let bytes = vec![
50 0b00000001, 0b11000000, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, ];
54 assert_variant!(
55 CtrlBody::parse(CtrlSubtype::PS_POLL, &bytes[..]),
56 Some(CtrlBody::PsPoll { ps_poll }) => {
57 assert_eq!(0b1100000000000001, { ps_poll.masked_aid });
58 assert_eq!(Bssid::from([2; 6]), ps_poll.bssid);
59 assert_eq!(MacAddr::from([4; 6]), ps_poll.ta);
60 },
61 "expected PS-Poll frame"
62 );
63 }
64}