use crate::error::{CrafterError, Result};
use crate::protocols::rsn::RsnInformation;
use super::{DOT11_TAG_DS_PARAMETER_SET, DOT11_TAG_RSN, DOT11_TAG_SSID};
use super::{DOT11_TAG_SUPPORTED_RATES, DOT11_TAG_TIM};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Dot11TaggedParameter {
id: u8,
length: usize,
data: Vec<u8>,
}
impl Dot11TaggedParameter {
pub fn new(id: u8, data: impl Into<Vec<u8>>) -> Self {
let data = data.into();
let length = data.len();
Self { id, length, data }
}
pub fn ssid(ssid: impl Into<Vec<u8>>) -> Self {
Self::new(DOT11_TAG_SSID, ssid)
}
pub fn supported_rates(rates: impl Into<Vec<u8>>) -> Self {
Self::new(DOT11_TAG_SUPPORTED_RATES, rates)
}
pub fn ds_parameter_set(current_channel: u8) -> Self {
Self::new(DOT11_TAG_DS_PARAMETER_SET, [current_channel])
}
pub fn tim(data: impl Into<Vec<u8>>) -> Self {
Self::new(DOT11_TAG_TIM, data)
}
pub fn rsn(data: impl Into<Vec<u8>>) -> Self {
Self::new(DOT11_TAG_RSN, data)
}
pub fn from_rsn_information(rsn: &RsnInformation) -> Result<Self> {
let data = rsn.to_tagged_parameter_value()?;
if data.len() > u8::MAX as usize {
return Err(CrafterError::invalid_field_value(
"dot11.tagged_parameter.length",
"tagged parameter length must fit in one byte",
));
}
Ok(Self::rsn(data))
}
pub fn rsn_information(&self) -> Option<Result<RsnInformation>> {
if self.id == DOT11_TAG_RSN {
Some(RsnInformation::from_tagged_parameter_value(&self.data))
} else {
None
}
}
pub const fn id(&self) -> u8 {
self.id
}
pub const fn length(&self) -> usize {
self.length
}
pub fn data(&self) -> &[u8] {
&self.data
}
pub fn value(&self) -> &[u8] {
&self.data
}
pub fn with_length(mut self, length: u8) -> Self {
self.length = length as usize;
self
}
pub fn encoded_len(&self) -> usize {
2 + self.data.len()
}
pub(super) fn from_wire(id: u8, length: u8, data: &[u8]) -> Self {
Self {
id,
length: length as usize,
data: data.to_vec(),
}
}
pub(super) fn compile(&self, out: &mut Vec<u8>) -> Result<()> {
if self.length > u8::MAX as usize {
return Err(CrafterError::invalid_field_value(
"dot11.tagged_parameter.length",
"tagged parameter length must fit in one byte",
));
}
out.push(self.id);
out.push(self.length as u8);
out.extend_from_slice(&self.data);
Ok(())
}
}