use heterob::{bit_numbering::Lsb, endianness::LeBytesTryInto, Seq, P3};
use super::ExtendedCapabilityDataError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VendorSpecificExtendedCapability<'a> {
pub header: VsecHeader,
pub registers: VsecRegisters<'a>,
}
impl<'a> TryFrom<&'a [u8]> for VendorSpecificExtendedCapability<'a> {
type Error = ExtendedCapabilityDataError;
fn try_from(slice: &'a [u8]) -> Result<Self, Self::Error> {
let Seq { head: header, tail } =
slice
.le_bytes_try_into()
.map_err(|_| ExtendedCapabilityDataError {
name: "Vendor-Specific Extended Capability",
size: 4,
})?;
let Lsb((vsec_id, vsec_rev, vsec_length)) = P3::<u32, 16, 4, 12>(header).into();
let header = VsecHeader {
vsec_id,
vsec_rev,
vsec_length,
};
let registers = if let Some(len) = vsec_length.checked_sub(8) {
if let Some(slice) = tail.get(..len.into()) {
VsecRegisters::Valid(slice)
} else {
VsecRegisters::Incomplete(tail)
}
} else {
VsecRegisters::InvalidLength(vsec_length)
};
Ok(Self { header, registers })
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VsecHeader {
pub vsec_id: u16,
pub vsec_rev: u8,
pub vsec_length: u16,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VsecRegisters<'a> {
Valid(&'a [u8]),
InvalidLength(u16),
Incomplete(&'a [u8]),
}