use crate::error::ParseError;
use super::address::MacAddress;
use super::ether_type::EtherType;
pub(super) const HEADER_LENGTH: usize = 14;
const DESTINATION: core::ops::Range<usize> = 0..6;
const SOURCE: core::ops::Range<usize> = 6..12;
const ETHER_TYPE: core::ops::Range<usize> = 12..14;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EthernetFrame<'a> {
bytes: &'a [u8],
}
impl<'a> EthernetFrame<'a> {
pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
validate_frame_length(bytes.len())?;
Ok(Self { bytes })
}
#[inline]
pub fn destination(&self) -> MacAddress {
MacAddress::new(
self.bytes[DESTINATION]
.try_into()
.expect("validated header"),
)
}
#[inline]
pub fn source(&self) -> MacAddress {
MacAddress::new(self.bytes[SOURCE].try_into().expect("validated header"))
}
#[inline]
pub fn ether_type(&self) -> EtherType {
EtherType::new(u16::from_be_bytes(
self.bytes[ETHER_TYPE].try_into().expect("validated header"),
))
}
#[inline]
pub fn payload(&self) -> &'a [u8] {
&self.bytes[HEADER_LENGTH..]
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct EthernetFrameMut<'a> {
bytes: &'a mut [u8],
}
impl<'a> EthernetFrameMut<'a> {
pub(super) fn from_validated(bytes: &'a mut [u8]) -> Self {
Self { bytes }
}
pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
validate_frame_length(bytes.len())?;
Ok(Self { bytes })
}
#[inline]
pub fn destination(&self) -> MacAddress {
MacAddress::new(
self.bytes[DESTINATION]
.try_into()
.expect("validated header"),
)
}
#[inline]
pub fn source(&self) -> MacAddress {
MacAddress::new(self.bytes[SOURCE].try_into().expect("validated header"))
}
#[inline]
pub fn ether_type(&self) -> EtherType {
EtherType::new(u16::from_be_bytes(
self.bytes[ETHER_TYPE].try_into().expect("validated header"),
))
}
#[inline]
pub fn set_destination(&mut self, address: MacAddress) {
self.bytes[DESTINATION].copy_from_slice(&address.octets());
}
#[inline]
pub fn set_source(&mut self, address: MacAddress) {
self.bytes[SOURCE].copy_from_slice(&address.octets());
}
#[inline]
pub fn set_ether_type(&mut self, ether_type: EtherType) {
self.bytes[ETHER_TYPE].copy_from_slice(ðer_type.raw().to_be_bytes());
}
#[inline]
pub fn payload(&self) -> &[u8] {
&self.bytes[HEADER_LENGTH..]
}
#[inline]
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.bytes[HEADER_LENGTH..]
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
self.bytes
}
#[inline]
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
self.bytes
}
}
fn validate_frame_length(available: usize) -> Result<(), ParseError> {
if available < HEADER_LENGTH {
return Err(ParseError::Truncated {
minimum: HEADER_LENGTH,
available,
});
}
Ok(())
}