#![no_std]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use ether_type::EtherType;
use mac_parser::*;
use scroll::{
ctx::{MeasureWith, SizeWith, TryFromCtx, TryIntoCtx},
Endian, Pread, Pwrite,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Ethernet2Header {
pub dst: MACAddress,
pub src: MACAddress,
pub ether_type: EtherType,
}
impl Ethernet2Header {
pub const HEADER_LENGTH: usize = 14;
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
bytes.pread(0).ok()
}
pub fn from_fixed_bytes(bytes: [u8; Self::HEADER_LENGTH]) -> Self {
Self::from_bytes(bytes.as_slice()).unwrap()
}
pub fn to_bytes(self, buf: &mut [u8]) -> Option<()> {
buf.pwrite(self, 0).ok().map(|_| ())
}
pub fn to_fixed_bytes(self) -> [u8; Self::HEADER_LENGTH] {
let mut buf = [0x00; Self::HEADER_LENGTH];
buf.as_mut_slice().pwrite(self, 0).unwrap();
buf
}
}
impl SizeWith for Ethernet2Header {
fn size_with(_ctx: &()) -> usize {
Self::HEADER_LENGTH
}
}
impl TryFromCtx<'_> for Ethernet2Header {
type Error = scroll::Error;
fn try_from_ctx(from: &'_ [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
let mut offset = 0;
let dst = from.gread(&mut offset)?;
let src = from.gread(&mut offset)?;
let ether_type = EtherType::from_bits(from.gread_with(&mut offset, Endian::Big)?);
Ok((
Self {
dst,
src,
ether_type,
},
offset,
))
}
}
impl TryIntoCtx for Ethernet2Header {
type Error = scroll::Error;
fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
let mut offset = 0;
buf.gwrite(self.dst, &mut offset)?;
buf.gwrite(self.src, &mut offset)?;
buf.gwrite_with(
self.ether_type.into_bits(),
&mut offset,
Endian::Big,
)?;
Ok(offset)
}
}
pub struct Ethernet2Frame<'a> {
pub header: Ethernet2Header,
pub payload: &'a [u8],
}
impl Ethernet2Frame<'_> {
pub const fn length_in_bytes(&self) -> usize {
Ethernet2Header::HEADER_LENGTH + self.payload.len()
}
pub fn from_bytes<'a>(bytes: &'a [u8]) -> Option<Ethernet2Frame<'a>> {
bytes.pread(0).ok()
}
pub fn to_bytes(self, buf: &mut [u8]) -> Option<()> {
buf.pwrite(self, 0).ok().map(|_| ())
}
}
impl MeasureWith<()> for Ethernet2Frame<'_> {
fn measure_with(&self, _ctx: &()) -> usize {
self.length_in_bytes()
}
}
impl<'a> TryFromCtx<'a> for Ethernet2Frame<'a> {
type Error = scroll::Error;
fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
if from.len() <= 14 {
return Err(scroll::Error::BadInput {
size: 0,
msg: "Ethernet frame has no body.",
});
}
let mut offset = 0;
let header = from.gread(&mut offset)?;
let payload = from.gread_with(&mut offset, from.len() - Ethernet2Header::HEADER_LENGTH)?;
Ok((Self { header, payload }, offset))
}
}
impl TryIntoCtx for Ethernet2Frame<'_> {
type Error = scroll::Error;
fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
let mut offset = 0;
buf.gwrite(self.header, &mut offset)?;
buf.gwrite(self.payload, &mut offset)?;
Ok(offset)
}
}
#[cfg(feature = "alloc")]
pub struct OwnedEthernet2Frame {
pub header: Ethernet2Header,
pub payload: Vec<u8>
}
#[cfg(feature = "alloc")]
impl TryFromCtx<'_> for OwnedEthernet2Frame {
type Error = scroll::Error;
fn try_from_ctx(from: &'_ [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
let mut offset = 0;
let ethernet_frame = from.gread::<Ethernet2Frame<'_>>(&mut offset)?;
Ok((
Self {
header: ethernet_frame.header,
payload: ethernet_frame.payload.to_vec()
},
offset
))
}
}
#[cfg(feature = "alloc")]
impl TryIntoCtx for OwnedEthernet2Frame {
type Error = scroll::Error;
fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
let ethernet_frame = Ethernet2Frame {
header: self.header,
payload: self.payload.as_slice(),
};
buf.pwrite(ethernet_frame, 0)
}
}