use crate::MacAddr;
use byte_struct::*;
use ufmt::derive::uDebug;
use static_assertions::const_assert;
const_assert!(EthernetHeader::BYTE_LEN == 14);
#[derive(ByteStruct, Clone, Copy, uDebug, Debug, PartialEq, Eq)]
#[byte_struct_be]
pub struct EthernetHeader {
pub dst_macaddr: MacAddr,
pub src_macaddr: MacAddr,
pub ethertype: EtherType,
}
impl EthernetHeader {
pub fn to_be_bytes(&self) -> [u8; Self::BYTE_LEN] {
let mut bytes = [0_u8; Self::BYTE_LEN];
self.write_bytes(&mut bytes);
bytes
}
}
#[derive(Clone, Copy, uDebug, Debug, PartialEq, Eq)]
pub struct EthernetFrame<T>
where
T: ByteStruct,
{
pub header: EthernetHeader,
pub data: T,
pub checksum: u32,
}
impl<T> ByteStructLen for EthernetFrame<T>
where
T: ByteStruct,
{
const BYTE_LEN: usize = EthernetHeader::BYTE_LEN + T::BYTE_LEN + 4;
}
impl<T> ByteStruct for EthernetFrame<T>
where
T: ByteStruct,
{
fn read_bytes(bytes: &[u8]) -> Self {
let mut checksum_bytes = [0_u8; 4];
checksum_bytes.copy_from_slice(&bytes[Self::BYTE_LEN - 4..Self::BYTE_LEN]);
EthernetFrame::<T> {
header: EthernetHeader::read_bytes(&bytes[0..EthernetHeader::BYTE_LEN]),
data: T::read_bytes(&bytes[EthernetHeader::BYTE_LEN..Self::BYTE_LEN - 4]),
checksum: u32::from_be_bytes(checksum_bytes),
}
}
fn write_bytes(&self, bytes: &mut [u8]) {
self.header
.write_bytes(&mut bytes[0..EthernetHeader::BYTE_LEN]);
self.data
.write_bytes(&mut bytes[EthernetHeader::BYTE_LEN..Self::BYTE_LEN - 4]);
let checksum_bytes = self.checksum.to_be_bytes();
for i in 0..4 {
bytes[Self::BYTE_LEN - 4 + i] = checksum_bytes[i];
}
}
}
impl<T> EthernetFrame<T>
where
T: ByteStruct,
{
pub fn to_be_bytes(&self) -> [u8; Self::BYTE_LEN] {
let mut bytes = [0_u8; Self::BYTE_LEN];
self.write_bytes(&mut bytes);
bytes
}
}
#[derive(Clone, Copy, uDebug, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u16)]
pub enum EtherType {
IpV4 = 0x0800,
Arp = 0x0806,
Vlan = 0x8100,
IpV6 = 0x86DD,
EtherCat = 0x88A4,
Ptp = 0x88A7,
Unimplemented = 0x0,
}
impl From<u16> for EtherType {
fn from(value: u16) -> Self {
match value {
x if x == EtherType::Arp as u16 => EtherType::Arp,
x if x == EtherType::EtherCat as u16 => EtherType::EtherCat,
x if x == EtherType::IpV4 as u16 => EtherType::IpV4,
x if x == EtherType::IpV6 as u16 => EtherType::IpV6,
x if x == EtherType::Ptp as u16 => EtherType::Ptp,
x if x == EtherType::Vlan as u16 => EtherType::Vlan,
_ => EtherType::Unimplemented,
}
}
}
impl ByteStructLen for EtherType {
const BYTE_LEN: usize = 2;
}
impl ByteStruct for EtherType {
fn read_bytes(bytes: &[u8]) -> Self {
let mut bytes_read = [0_u8; 2];
bytes_read.copy_from_slice(&bytes[0..=1]);
return EtherType::from(u16::from_be_bytes(bytes_read));
}
fn write_bytes(&self, bytes: &mut [u8]) {
let bytes_to_write = (*self as u16).to_be_bytes();
bytes[0] = bytes_to_write[0];
bytes[1] = bytes_to_write[1];
}
}
impl EtherType {
pub fn to_be_bytes(&self) -> [u8; Self::BYTE_LEN] {
(*self as u16).to_be_bytes()
}
}