Skip to content

Commit

Permalink
Change MacAddr to hold u64 instead of byte array
Browse files Browse the repository at this point in the history
Compiler probably does this anyway. And this way we can have access to
upper two bytes if we want to.
  • Loading branch information
oherrala committed Oct 24, 2022
1 parent d54f685 commit dc560c9
Showing 1 changed file with 54 additions and 37 deletions.
91 changes: 54 additions & 37 deletions luomu-common/src/macaddr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};
use std::fmt;

use super::InvalidAddress;
Expand All @@ -10,55 +10,71 @@ use super::InvalidAddress;
/// address to reside in lowest 6 bytes. All `From<MacAddr>` and
/// `TryFrom<MacAddr>` implementations return their bytes as big endian.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MacAddr([u8; 6]);
pub struct MacAddr(u64);

impl MacAddr {
/// A broadcast MAC address (FF:FF:FF:FF:FF:FF)
pub const BROADCAST: MacAddr = MacAddr(0x0000FFFFFFFFFFFF);
}

impl From<[u8; 6]> for MacAddr {
fn from(val: [u8; 6]) -> Self {
Self(val)
fn from(v: [u8; 6]) -> Self {
Self::from(&v)
}
}

impl From<&[u8; 6]> for MacAddr {
fn from(val: &[u8; 6]) -> Self {
Self(val.to_owned())
fn from(v: &[u8; 6]) -> Self {
let r = (u64::from(v[0]) << 40)
+ (u64::from(v[1]) << 32)
+ (u64::from(v[2]) << 24)
+ (u64::from(v[3]) << 16)
+ (u64::from(v[4]) << 8)
+ u64::from(v[5]);
Self(r)
}
}

impl From<MacAddr> for [u8; 6] {
fn from(val: MacAddr) -> Self {
val.0
impl TryFrom<u64> for MacAddr {
type Error = InvalidAddress;

fn try_from(mac: u64) -> Result<Self, Self::Error> {
if mac > 0x0000FFFFFFFFFFFF {
return Err(InvalidAddress);
}

Ok(Self(mac))
}
}

impl<'a> From<&'a MacAddr> for &'a [u8; 6] {
fn from(val: &'a MacAddr) -> Self {
&val.0
impl From<MacAddr> for u64 {
fn from(mac: MacAddr) -> Self {
mac.0
}
}

impl<'a> From<&'a MacAddr> for &'a [u8] {
fn from(val: &'a MacAddr) -> Self {
&val.0
impl From<&MacAddr> for u64 {
fn from(mac: &MacAddr) -> Self {
mac.0
}
}

impl TryFrom<u64> for MacAddr {
type Error = InvalidAddress;

fn try_from(mac: u64) -> Result<Self, Self::Error> {
if mac > 0x0000FFFFFFFFFFFF {
return Err(InvalidAddress);
}
impl From<MacAddr> for [u8; 6] {
fn from(mac: MacAddr) -> Self {
(&mac).into()
}
}

let b = mac.to_be_bytes();
Ok(MacAddr([b[2], b[3], b[4], b[5], b[6], b[7]]))
impl From<&MacAddr> for [u8; 6] {
fn from(mac: &MacAddr) -> Self {
u64::from(mac).to_be_bytes()[2..=7].try_into().unwrap()
}
}

impl fmt::Debug for MacAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let h = self
.0
let b: [u8; 6] = self.into();
let h = b
.iter()
.map(|b| format!("{:02x}", b))
.collect::<Vec<_>>()
Expand All @@ -67,13 +83,6 @@ impl fmt::Debug for MacAddr {
}
}

impl std::ops::Deref for MacAddr {
type Target = [u8; 6];
fn deref(&self) -> &Self::Target {
&self.0
}
}

#[cfg(test)]
mod tests {
use std::convert::TryFrom;
Expand All @@ -89,6 +98,14 @@ mod tests {
assert_eq!(&debug, "00:ff:11:ee:22:dd");
}

#[test]
fn test_mac_to_array() {
let slice = [0x00, 0xff, 0x11, 0xee, 0x22, 0xdd];
let mac: MacAddr = slice.into();
let array: [u8; 6] = mac.into();
assert_eq!(slice, array);
}

#[test]
fn test_try_from_u64_bounds() {
let i0 = 0x0000000000000000;
Expand All @@ -108,15 +125,15 @@ mod tests {
fn test_try_from_u64_byteoder() {
let i = 0x0000123456789ABC;
let mac = MacAddr::try_from(i).unwrap();
let b: &[u8] = (&mac).into();
assert_eq!(b, &[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]);
let b: [u8; 6] = mac.into();
assert_eq!(&b, &[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]);
}

quickcheck! {
fn prop_macaddr_to_from(xs: (u8, u8, u8, u8, u8, u8)) -> bool {
let b1 = &[xs.0, xs.1, xs.2, xs.3, xs.4, xs.5];
let b1: [u8; 6] = [xs.0, xs.1, xs.2, xs.3, xs.4, xs.5];
let mac = MacAddr::from(b1);
let b2: &[u8] = (&mac).into();
let b2: [u8; 6] = mac.into();
b1 == b2
}
}
Expand Down

0 comments on commit dc560c9

Please sign in to comment.