use crate::descriptors::entry_list::{Entry, MacAddress, list_len, parse_list, write_list};
use crate::error::Result;
use alloc::vec::Vec;
use broadcast_common::{Parse, Serialize};
pub const TAG: u8 = 0x0E;
const ENTRY_LEN: usize = 12;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct MacAddressRange {
pub low: MacAddress,
pub high: MacAddress,
}
impl Entry<ENTRY_LEN> for MacAddressRange {
fn read(b: &[u8; ENTRY_LEN]) -> Self {
let (low, high) = b.split_at(6);
Self {
low: low.try_into().unwrap_or_default(),
high: high.try_into().unwrap_or_default(),
}
}
fn write(&self, b: &mut [u8; ENTRY_LEN]) {
b[..6].copy_from_slice(&self.low);
b[6..].copy_from_slice(&self.high);
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
pub struct TargetMacAddressRangeDescriptor<'a> {
pub ranges: Vec<MacAddressRange>,
pub trailing: &'a [u8],
}
impl<'a> Parse<'a> for TargetMacAddressRangeDescriptor<'a> {
type Error = crate::error::Error;
fn parse(bytes: &'a [u8]) -> Result<Self> {
let (ranges, trailing) = parse_list::<ENTRY_LEN, MacAddressRange>(
bytes,
TAG,
"TargetMacAddressRangeDescriptor",
)?;
Ok(Self { ranges, trailing })
}
}
impl Serialize for TargetMacAddressRangeDescriptor<'_> {
type Error = crate::error::Error;
fn serialized_len(&self) -> usize {
list_len(self.ranges.len(), ENTRY_LEN, self.trailing.len())
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
write_list::<ENTRY_LEN, _>(buf, TAG, &self.ranges, self.trailing)
}
}
impl<'a> crate::traits::DescriptorDef<'a> for TargetMacAddressRangeDescriptor<'a> {
const TAG: u8 = TAG;
const NAME: &'static str = "TARGET_MAC_ADDRESS_RANGE";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialize_rejects_entry_sized_trailing() {
let mut d = TargetMacAddressRangeDescriptor::parse(&[TAG, 0]).unwrap();
let long = [0u8; ENTRY_LEN];
d.trailing = &long;
assert!(d.serialize_into(&mut [0u8; 64]).is_err());
let mut buf = [0u8; 64];
d.trailing = &long[..ENTRY_LEN - 1];
let n = d.serialize_into(&mut buf).unwrap();
assert_eq!(
TargetMacAddressRangeDescriptor::parse(&buf[..n]).unwrap(),
d
);
}
#[test]
fn parse_and_round_trip() {
let bytes = [
TAG, 12, 0x12, 0x78, 0x65, 0x32, 0x59, 0x32, 0x78, 0x44, 0x54, 0x54, 0x98, 0x87,
];
let d = TargetMacAddressRangeDescriptor::parse(&bytes).unwrap();
assert_eq!(d.ranges.len(), 1);
assert_eq!(d.ranges[0].low, [0x12, 0x78, 0x65, 0x32, 0x59, 0x32]);
assert_eq!(d.ranges[0].high, [0x78, 0x44, 0x54, 0x54, 0x98, 0x87]);
let mut out = vec![0u8; d.serialized_len()];
d.serialize_into(&mut out).unwrap();
assert_eq!(out, bytes);
}
#[test]
fn empty_and_partial_tail_round_trip() {
for bytes in [&[TAG, 0][..], &[TAG, 3, 1, 2, 3][..]] {
let d = TargetMacAddressRangeDescriptor::parse(bytes).unwrap();
let mut out = vec![0u8; d.serialized_len()];
d.serialize_into(&mut out).unwrap();
assert_eq!(out, bytes);
}
assert!(TargetMacAddressRangeDescriptor::parse(&[0x0F, 0]).is_err());
}
}