1use std::error::Error;
2use std::fmt;
3use std::str::FromStr;
4
5#[derive(Debug, Eq, PartialEq)]
6pub struct MacAddrLengthError;
7
8impl fmt::Display for MacAddrLengthError {
9 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10 self.description().fmt(f)
11 }
12}
13
14impl Error for MacAddrLengthError {
15 fn description(&self) -> &str {
16 "Given data not six bytes long"
17 }
18}
19
20#[derive(Copy, Clone, Default, Eq, PartialEq, Hash)]
22pub struct MacAddr(pub [u8; 6]);
23
24impl MacAddr {
25 pub const BROADCAST: MacAddr = MacAddr([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
27
28 pub fn try_from_slice(slice: &[u8]) -> Result<MacAddr, MacAddrLengthError> {
31 if slice.len() == 6 {
32 Ok(Self::from_slice(slice))
33 } else {
34 Err(MacAddrLengthError)
35 }
36 }
37
38 pub fn from_slice(slice: &[u8]) -> MacAddr {
42 let mut mac = MacAddr::default();
43 <[u8; 6] as AsMut<[u8]>>::as_mut(&mut mac.0).copy_from_slice(slice);
44 mac
45 }
46
47 pub fn from_bytes(b0: u8, b1: u8, b2: u8, b3: u8, b4: u8, b5: u8) -> MacAddr {
49 MacAddr([b0, b1, b2, b3, b4, b5])
50 }
51}
52
53impl AsRef<[u8]> for MacAddr {
54 fn as_ref(&self) -> &[u8] {
55 &self.0[..]
56 }
57}
58
59impl AsRef<[u8; 6]> for MacAddr {
60 fn as_ref(&self) -> &[u8; 6] {
61 &self.0
62 }
63}
64
65impl From<[u8; 6]> for MacAddr {
66 fn from(data: [u8; 6]) -> Self {
67 MacAddr(data)
68 }
69}
70
71#[derive(Debug, Eq, PartialEq)]
72pub struct MacAddrParseError(String);
73
74impl fmt::Display for MacAddrParseError {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 write!(f, "Invalid MAC string: {}", self.0)
77 }
78}
79
80impl Error for MacAddrParseError {
81 fn description(&self) -> &str {
82 "Invalid MAC address string"
83 }
84}
85
86impl FromStr for MacAddr {
87 type Err = MacAddrParseError;
88
89 fn from_str(s: &str) -> Result<Self, Self::Err> {
90 use std::num::ParseIntError;
91
92 let bytes: Result<Vec<u8>, ParseIntError> =
93 s.split(":").map(|s| u8::from_str_radix(s, 16)).collect();
94 match bytes {
95 Ok(ref bytes) if bytes.len() == 6 => Ok(Self::from_slice(&bytes)),
96 _ => Err(MacAddrParseError(s.to_owned())),
97 }
98 }
99}
100
101impl fmt::Display for MacAddr {
102 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 write!(
106 f,
107 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
108 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
109 )
110 }
111}
112
113impl fmt::Debug for MacAddr {
114 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 (self as &fmt::Display).fmt(f)
116 }
117}
118
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn from_slice() {
126 let data = [5, 6, 7, 8, 9, 10];
127 let mac = MacAddr::from_slice(&data[..]);
128 assert_eq!(data, mac.as_ref());
129 }
130
131 #[test]
132 #[should_panic]
133 fn from_short_slice() {
134 MacAddr::from_slice(&[1, 2, 3, 4, 5]);
135 }
136
137 #[test]
138 #[should_panic]
139 fn from_long_slice() {
140 MacAddr::from_slice(&[1, 2, 3, 4, 5, 6, 7]);
141 }
142
143 #[test]
144 fn from_bytes() {
145 let mac = MacAddr::from_bytes(2, 3, 4, 5, 6, 7);
146 assert_eq!([2, 3, 4, 5, 6, 7], mac.as_ref());
147 }
148
149 #[test]
150 fn as_ref() {
151 let data = [5, 6, 7, 8, 9, 10];
152 let mac = MacAddr(data);
153 assert_eq!(data, mac.as_ref());
154 }
155
156 #[test]
157 fn display() {
158 let mac = MacAddr([255, 6, 7, 8, 9, 10]);
159 assert_eq!("ff:06:07:08:09:0a", mac.to_string());
160 }
161
162 #[test]
163 fn from_str() {
164 let result = MacAddr::from_str("01:02:ff:ac:13:37");
165 assert_eq!(result, Ok(MacAddr([0x01, 0x02, 0xff, 0xac, 0x13, 0x37])));
166 }
167}