1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    super::CtrlSubtype,
    zerocopy::{ByteSlice, Ref},
};

mod fields;

pub use fields::*;

#[derive(Debug)]
pub enum CtrlBody<B: ByteSlice> {
    PsPoll { ps_poll: Ref<B, PsPoll> },
    Unsupported { subtype: CtrlSubtype },
}

impl<B: ByteSlice> CtrlBody<B> {
    pub fn parse(subtype: CtrlSubtype, bytes: B) -> Option<Self> {
        match subtype {
            CtrlSubtype::PS_POLL => {
                let (ps_poll, _) = Ref::new_unaligned_from_prefix(bytes)?;
                Some(CtrlBody::PsPoll { ps_poll })
            }
            subtype => Some(CtrlBody::Unsupported { subtype }),
        }
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::assert_variant,
        ieee80211::{Bssid, MacAddr},
    };

    #[test]
    fn parse_ps_poll_frame() {
        let bytes = vec![
            0b00000001, 0b11000000, // Masked AID
            2, 2, 2, 2, 2, 2, // addr1
            4, 4, 4, 4, 4, 4, // addr2
        ];
        assert_variant!(
            CtrlBody::parse(CtrlSubtype::PS_POLL, &bytes[..]),
            Some(CtrlBody::PsPoll { ps_poll }) => {
                assert_eq!(0b1100000000000001, { ps_poll.masked_aid });
                assert_eq!(Bssid::from([2; 6]), ps_poll.bssid);
                assert_eq!(MacAddr::from([4; 6]), ps_poll.ta);
            },
            "expected PS-Poll frame"
        );
    }
}