mac_parser/
lib.rs

1#![no_std]
2
3use core::{
4    fmt::{Debug, Display},
5    ops::{Deref, DerefMut, Index, IndexMut},
6};
7
8use scroll::{
9    ctx::{SizeWith, TryFromCtx, TryIntoCtx},
10    Pread, Pwrite,
11};
12
13/// The broadcast address.
14pub const BROADCAST: MACAddress = MACAddress::new([0xff; 6]);
15/// An empty address.
16pub const ZERO: MACAddress = MACAddress::new([0x00; 6]);
17
18#[repr(transparent)]
19#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
20/// A MAC address.
21pub struct MACAddress(pub [u8; 6]);
22impl MACAddress {
23    /// Checks the unicast/multicast bit of the first octet.
24    pub const fn is_multicast(&self) -> bool {
25        self.0[0] & 0x1 != 0x0
26    }
27    /// Checks the global/local bit of the first octet.
28    pub const fn is_local(&self) -> bool {
29        self.0[0] & 0x2 != 0x0
30    }
31    pub const fn new(address: [u8; 6]) -> Self {
32        Self(address)
33    }
34}
35impl From<[u8; 6]> for MACAddress {
36    fn from(value: [u8; 6]) -> Self {
37        Self(value)
38    }
39}
40impl From<MACAddress> for [u8; 6] {
41    fn from(value: MACAddress) -> Self {
42        *value.deref()
43    }
44}
45impl SizeWith for MACAddress {
46    fn size_with(_ctx: &()) -> usize {
47        6
48    }
49}
50impl TryFromCtx<'_> for MACAddress {
51    type Error = scroll::Error;
52    #[inline]
53    fn try_from_ctx(from: &'_ [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
54        Ok((MACAddress::new(from.pread(0)?), 6))
55    }
56}
57impl TryIntoCtx for MACAddress {
58    type Error = scroll::Error;
59    #[inline]
60    fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
61        buf.pwrite(self.as_slice(), 0)
62    }
63}
64impl Deref for MACAddress {
65    type Target = [u8; 6];
66    fn deref(&self) -> &Self::Target {
67        &self.0
68    }
69}
70impl DerefMut for MACAddress {
71    fn deref_mut(&mut self) -> &mut Self::Target {
72        &mut self.0
73    }
74}
75impl Index<usize> for MACAddress {
76    type Output = u8;
77    fn index(&self, index: usize) -> &Self::Output {
78        &self.0[index]
79    }
80}
81impl IndexMut<usize> for MACAddress {
82    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
83        &mut self.0[index]
84    }
85}
86impl Debug for MACAddress {
87    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88        <Self as core::fmt::Display>::fmt(&self, f)
89    }
90}
91impl Display for MACAddress {
92    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
93        f.write_fmt(format_args!(
94            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
95            self[0], self[1], self[2], self[3], self[4], self[5]
96        ))
97    }
98}
99#[cfg(feature = "defmt")]
100impl defmt::Format for MACAddress {
101    fn format(&self, fmt: defmt::Formatter) {
102        defmt::write!(
103            fmt,
104            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
105            self[0],
106            self[1],
107            self[2],
108            self[3],
109            self[4],
110            self[5]
111        )
112    }
113}