use nom::{
IResult,
bits::{bits, complete::take},
error::Error,
};
use crate::frame::components::FrameControl;
use crate::frame_types::*;
pub fn parse_frame_control(input: &[u8]) -> IResult<&[u8], FrameControl> {
let (remaining, (frame_subtype, frame_type, protocol_version, flags)) =
bits::<_, (u8, u8, u8, u8), Error<(&[u8], usize)>, _, _>((
take(4usize),
take(2usize),
take(2usize),
take(8usize),
))(input)?;
let protocol_version = parse_protocol_version(protocol_version);
let frame_type = parse_frame_type(frame_type);
let frame_subtype = match frame_type {
FrameType::Management => management_frame_subtype(frame_subtype),
FrameType::Control => control_frame_subtype(frame_subtype),
FrameType::Data => data_frame_subtype(frame_subtype),
FrameType::Extension => extension_frame_subtype(frame_subtype),
FrameType::Unknown(_) => FrameSubType::Unhandled(frame_subtype),
};
Ok((
remaining,
FrameControl {
protocol_version,
frame_type,
frame_subtype,
flags,
},
))
}
fn parse_protocol_version(byte: u8) -> FrameProtocolVersion {
match byte {
0 => FrameProtocolVersion::PV0,
n => FrameProtocolVersion::Unknown(n),
}
}
fn parse_frame_type(byte: u8) -> FrameType {
match byte {
0 => FrameType::Management,
1 => FrameType::Control,
2 => FrameType::Data,
3 => FrameType::Extension,
byte => FrameType::Unknown(byte),
}
}
fn management_frame_subtype(byte: u8) -> FrameSubType {
match byte {
0 => FrameSubType::AssociationRequest,
1 => FrameSubType::AssociationResponse,
2 => FrameSubType::ReassociationRequest,
3 => FrameSubType::ReassociationResponse,
4 => FrameSubType::ProbeRequest,
5 => FrameSubType::ProbeResponse,
6 => FrameSubType::TimingAdvertisement,
7 => FrameSubType::Reserved(byte),
8 => FrameSubType::Beacon,
9 => FrameSubType::Atim,
10 => FrameSubType::Disassociation,
11 => FrameSubType::Authentication,
12 => FrameSubType::Deauthentication,
13 => FrameSubType::Action,
14 => FrameSubType::ActionNoAck,
15 => FrameSubType::Reserved(byte),
x => FrameSubType::Unhandled(x),
}
}
fn control_frame_subtype(byte: u8) -> FrameSubType {
match byte {
0 => FrameSubType::Reserved(byte),
1 => FrameSubType::Reserved(byte),
2 => FrameSubType::Trigger,
3 => FrameSubType::Tack,
4 => FrameSubType::BeamformingReportPoll,
5 => FrameSubType::NdpAnnouncement,
6 => FrameSubType::ControlFrameExtension,
7 => FrameSubType::ControlWrapper,
8 => FrameSubType::BlockAckRequest,
9 => FrameSubType::BlockAck,
10 => FrameSubType::PsPoll,
11 => FrameSubType::Rts,
12 => FrameSubType::Cts,
13 => FrameSubType::Ack,
14 => FrameSubType::CfEnd,
15 => FrameSubType::CfEndCfAck,
x => FrameSubType::Unhandled(x),
}
}
fn extension_frame_subtype(byte: u8) -> FrameSubType {
match byte {
0 => FrameSubType::DMGBeacon,
1 => FrameSubType::S1GBeacon,
_ => FrameSubType::Reserved(byte),
}
}
fn data_frame_subtype(byte: u8) -> FrameSubType {
match byte {
0 => FrameSubType::Data,
1 => FrameSubType::DataCfAck,
2 => FrameSubType::DataCfPoll,
3 => FrameSubType::DataCfAckCfPoll,
4 => FrameSubType::NullData,
5 => FrameSubType::CfAck,
6 => FrameSubType::CfPoll,
7 => FrameSubType::CfAckCfPoll,
8 => FrameSubType::QosData,
9 => FrameSubType::QosDataCfAck,
10 => FrameSubType::QosDataCfPoll,
11 => FrameSubType::QosDataCfAckCfPoll,
12 => FrameSubType::QosNull,
13 => FrameSubType::Reserved(byte),
14 => FrameSubType::QosCfPoll,
15 => FrameSubType::QosCfAckCfPoll,
x => FrameSubType::Unhandled(x),
}
}