use crate::ieee::ethernet::{Address, EtherType};
use crate::{Buf, BufMut};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HeaderMapping<T> {
buffer: T,
}
impl<T> HeaderMapping<T> {
pub fn new(buffer: T) -> Self {
Self { buffer }
}
pub fn into_inner(self) -> T {
self.buffer
}
}
impl<T: Buf> HeaderMapping<T> {
pub fn read_destination_address(&self) -> Address {
unsafe { Address::new(self.buffer.get_array_unchecked::<6>(0)) }
}
pub fn read_source_address(&self) -> Address {
unsafe { Address::new(self.buffer.get_array_unchecked::<6>(6)) }
}
pub fn read_ether_type(&self) -> EtherType {
unsafe { EtherType(self.buffer.get_u16_be_unchecked(12)) }
}
}
impl<T: BufMut> HeaderMapping<T> {
pub fn write_destination_address(&mut self, addr: Address) {
unsafe { self.buffer.set_array_unchecked(0, &addr.0) }
}
pub fn write_source_address(&mut self, addr: Address) {
unsafe { self.buffer.set_array_unchecked(6, &addr.0) }
}
pub fn write_ether_type(&mut self, ether_type: EtherType) {
unsafe { self.buffer.set_u16_be_unchecked(12, ether_type.0) }
}
}
#[cfg(test)]
mod tests {
use super::{Address, EtherType, HeaderMapping};
#[test]
fn read_fields() {
let buffer = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x08, 0x00, ];
let mapping = HeaderMapping::new(&buffer[..]);
assert_eq!(mapping.read_destination_address(), Address::BROADCAST);
assert_eq!(
mapping.read_source_address(),
Address::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E])
);
assert_eq!(mapping.read_ether_type(), EtherType::IPV4);
}
#[test]
fn write_fields() {
let mut buffer = [0u8; 14];
{
let mut mapping = HeaderMapping::new(&mut buffer[..]);
mapping.write_destination_address(Address::BROADCAST);
mapping.write_source_address(Address::new([0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]));
mapping.write_ether_type(EtherType::IPV6);
}
assert_eq!(&buffer[0..6], &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
assert_eq!(&buffer[6..12], &[0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E]);
assert_eq!(&buffer[12..14], &[0x86, 0xDD]); }
}