kawaiifi 0.2.1

Wi-Fi scanning library for Linux, macOS, and Windows.
Documentation
use deku::{DekuContainerWrite, DekuRead, DekuWrite};
use serde::{Deserialize, Serialize};

use crate::ies::{BitRange, Field, IeId};

#[derive(Debug, Clone, PartialEq, Eq, Hash, DekuRead, DekuWrite, Serialize, Deserialize)]
pub struct SpatialReuseParameterSet {
    pub sr_control: SrControl,
    #[deku(cond = "sr_control.non_srg_offset_present", bytes = "1")]
    pub non_srg_obss_pd_max_offset: Option<u8>,
    #[deku(cond = "sr_control.srg_information_present", bytes = "1")]
    pub srg_obss_pd_min_offset: Option<u8>,
    #[deku(cond = "sr_control.srg_information_present", bytes = "1")]
    pub srg_obss_pd_max_offset: Option<u8>,
    #[deku(cond = "sr_control.srg_information_present", bytes = "8")]
    pub srg_bss_color_bitmap: Option<[u8; 8]>,
    #[deku(cond = "sr_control.srg_information_present", bytes = "8")]
    pub srg_partial_bssid_bitmap: Option<[u8; 8]>,
}

impl SpatialReuseParameterSet {
    pub const NAME: &'static str = "Spatial Reuse Parameter Set";
    pub const ID: u8 = 255;
    pub const ID_EXT: Option<u8> = Some(39);
    pub(crate) const IE_ID: IeId = IeId::new(Self::ID, Self::ID_EXT);

    pub fn summary(&self) -> String {
        "".to_string()
    }

    pub fn fields(&self) -> Vec<Field> {
        let mut fields = vec![self.sr_control.to_field()];

        if let Some(offset) = self.non_srg_obss_pd_max_offset {
            fields.push(
                Field::builder()
                    .title("Non-SRG OBSS PD Max Offset")
                    .value(offset)
                    .byte(offset)
                    .build(),
            );
        }

        if let Some(offset) = self.srg_obss_pd_min_offset {
            fields.push(
                Field::builder()
                    .title("SRG OBSS PD Min Offset")
                    .value(offset)
                    .byte(offset)
                    .build(),
            );
        }

        if let Some(offset) = self.srg_obss_pd_max_offset {
            fields.push(
                Field::builder()
                    .title("SRG OBSS PD Max Offset")
                    .value(offset)
                    .byte(offset)
                    .build(),
            );
        }

        fields
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, DekuRead, DekuWrite, Serialize, Deserialize)]
#[deku(bit_order = "lsb")]
pub struct SrControl {
    #[deku(bits = 1)]
    pub psr_disallowed: bool,
    #[deku(bits = 1)]
    pub non_srg_obss_pd_sr_disallowed: bool,
    #[deku(bits = 1)]
    pub non_srg_offset_present: bool,
    #[deku(bits = 1)]
    pub srg_information_present: bool,
    #[deku(bits = 1)]
    pub hesiga_spatial_reuse_value15_allowed: bool,
    #[deku(bits = 3)]
    reserved: u8,
}

impl SrControl {
    pub fn to_field(&self) -> Field {
        let byte = self
            .to_bytes()
            .unwrap_or_default()
            .first()
            .cloned()
            .unwrap_or_default();
        Field::builder()
            .title("SR Control")
            .value("")
            .byte(byte)
            .subfields([
                Field::builder()
                    .title("PSR Disallowed")
                    .value(self.psr_disallowed)
                    .bits(BitRange::new(&[byte], 0, 1))
                    .build(),
                Field::builder()
                    .title("Non-SRG OBSS PD SR Disallowed")
                    .value(self.non_srg_obss_pd_sr_disallowed)
                    .bits(BitRange::new(&[byte], 1, 1))
                    .build(),
                Field::builder()
                    .title("Non-SRG Offset Present")
                    .value(self.non_srg_offset_present)
                    .bits(BitRange::new(&[byte], 2, 1))
                    .build(),
                Field::builder()
                    .title("SRG Information Present")
                    .value(self.srg_information_present)
                    .bits(BitRange::new(&[byte], 3, 1))
                    .build(),
                Field::builder()
                    .title("HESIGA Spatial Reuse Value 15 Allowed")
                    .value(self.hesiga_spatial_reuse_value15_allowed)
                    .bits(BitRange::new(&[byte], 4, 1))
                    .build(),
                Field::reserved(BitRange::new(&[byte], 5, 3)),
            ])
            .build()
    }
}