use crate::*;
use ufmt::derive::uDebug;
use byte_struct::*;
use static_assertions::const_assert;
const_assert!(ArpPayload::BYTE_LEN == 46);
#[derive(ByteStruct, Clone, Copy, uDebug, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[byte_struct_be]
pub struct ArpPayload {
pub htype: u16,
pub ptype: ProtocolType,
pub hlen: u8,
pub plen: u8,
pub operation: ArpOperation,
pub src_mac: MacAddr,
pub src_ipaddr: IpV4Addr,
pub dst_mac: MacAddr,
pub dst_ipaddr: IpV4Addr,
_pad0: u128,
_pad1: u16
}
impl ArpPayload {
pub fn new(
src_mac: MacAddr,
src_ipaddr: IpV4Addr,
dst_mac: MacAddr,
dst_ipaddr: IpV4Addr,
operation: ArpOperation,
) -> Self {
ArpPayload {
htype: 1, ptype: ProtocolType::IpV4, hlen: 6,
plen: 4,
operation: operation,
src_mac: src_mac,
src_ipaddr: src_ipaddr,
dst_mac: dst_mac,
dst_ipaddr: dst_ipaddr,
_pad0: 0,
_pad1: 0
}
}
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 ArpOperation {
Request = 1,
Response = 2,
Unimplemented,
}
impl From<u16> for ArpOperation {
fn from(value: u16) -> Self {
match value {
x if x == ArpOperation::Request as u16 => ArpOperation::Request,
x if x == ArpOperation::Response as u16 => ArpOperation::Response,
_ => ArpOperation::Unimplemented,
}
}
}
impl ByteStructLen for ArpOperation {
const BYTE_LEN: usize = 2;
}
impl ByteStruct for ArpOperation {
fn read_bytes(bytes: &[u8]) -> Self {
let mut bytes_read = [0_u8; 2];
bytes_read.copy_from_slice(&bytes[0..=1]);
return ArpOperation::from(u16::from_be_bytes(bytes_read));
}
fn write_bytes(&self, bytes: &mut [u8]) {
let bytes_to_write = self.to_be_bytes();
bytes[0] = bytes_to_write[0];
bytes[1] = bytes_to_write[1];
}
}
impl ArpOperation {
pub fn to_be_bytes(&self) -> [u8; Self::BYTE_LEN] {
(*self as u16).to_be_bytes()
}
}
#[derive(Clone, Copy, uDebug, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u16)]
pub enum ProtocolType {
IpV4 = 0x0800,
Arp = 0x0806,
Vlan = 0x8100,
IpV6 = 0x86DD,
EtherCat = 0x88A4,
Ptp = 0x88A7,
Unimplemented = 0x0,
}
impl From<u16> for ProtocolType {
fn from(value: u16) -> Self {
match value {
x if x == ProtocolType::Arp as u16 => ProtocolType::Arp,
x if x == ProtocolType::EtherCat as u16 => ProtocolType::EtherCat,
x if x == ProtocolType::IpV4 as u16 => ProtocolType::IpV4,
x if x == ProtocolType::IpV6 as u16 => ProtocolType::IpV6,
x if x == ProtocolType::Ptp as u16 => ProtocolType::Ptp,
x if x == ProtocolType::Vlan as u16 => ProtocolType::Vlan,
_ => ProtocolType::Unimplemented,
}
}
}
impl ByteStructLen for ProtocolType {
const BYTE_LEN: usize = 2;
}
impl ByteStruct for ProtocolType {
fn read_bytes(bytes: &[u8]) -> Self {
let mut bytes_read = [0_u8; 2];
bytes_read.copy_from_slice(&bytes[0..=1]);
return ProtocolType::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 ProtocolType {
pub fn to_be_bytes(&self) -> [u8; Self::BYTE_LEN] {
(*self as u16).to_be_bytes()
}
}