1 use core::{fmt, str::FromStr}; 2 3 use crate::parser; 4 5 /// MAC address in *EUI-48* format. 6 #[repr(C)] 7 #[derive(Debug, Default, Hash, Eq, PartialEq, Ord, PartialOrd, Copy, Clone)] 8 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 9 pub struct MacAddr6([u8; 6]); 10 11 impl MacAddr6 { 12 /// Creates a new `MacAddr6` address from the bytes. 13 /// 14 /// ## Example 15 /// 16 /// ```rust 17 /// # use macaddr::MacAddr6; 18 /// let addr = MacAddr6::new(0x01, 0x23, 0x45, 0x67, 0x89, 0xAB); 19 /// ``` 20 #[allow(clippy::many_single_char_names)] new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr621 pub const fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr6 { 22 MacAddr6([a, b, c, d, e, f]) 23 } 24 25 /// Create a new nil `MacAddr6`. 26 /// 27 /// ## Example 28 /// 29 /// ```rust 30 /// # use macaddr::MacAddr6; 31 /// let addr = MacAddr6::nil(); 32 /// assert!(addr.is_nil()); 33 /// ``` nil() -> MacAddr634 pub const fn nil() -> MacAddr6 { 35 MacAddr6([0x00; 6]) 36 } 37 38 /// Create a new broadcast `MacAddr6`. 39 /// 40 /// ## Example 41 /// 42 /// ```rust 43 /// # use macaddr::MacAddr6; 44 /// let addr = MacAddr6::broadcast(); 45 /// assert!(addr.is_broadcast()); 46 /// ``` broadcast() -> MacAddr647 pub const fn broadcast() -> MacAddr6 { 48 MacAddr6([0xFF; 6]) 49 } 50 51 /// Returns `true` if the address is nil. 52 /// 53 /// ## Example 54 /// 55 /// ```rust 56 /// # use macaddr::MacAddr6; 57 /// let addr = MacAddr6::new(0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 58 /// 59 /// assert_eq!(addr.is_nil(), true); 60 /// ``` 61 #[allow(clippy::trivially_copy_pass_by_ref)] is_nil(&self) -> bool62 pub fn is_nil(&self) -> bool { 63 self.0.iter().all(|&b| b == 0) 64 } 65 66 /// Returns `true` if the address is broadcast. 67 /// 68 /// ## Example 69 /// 70 /// ```rust 71 /// # use macaddr::MacAddr6; 72 /// let addr = MacAddr6::new(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); 73 /// 74 /// assert_eq!(addr.is_broadcast(), true); 75 /// ``` 76 #[allow(clippy::trivially_copy_pass_by_ref)] is_broadcast(&self) -> bool77 pub fn is_broadcast(&self) -> bool { 78 self.0.iter().all(|&b| b == 0xFF) 79 } 80 81 /// Returns `true` if the address is unicast. 82 /// 83 /// ## Example 84 /// 85 /// ```rust 86 /// # use macaddr::MacAddr6; 87 /// let addr = MacAddr6::new(0x00, 0x01, 0x44, 0x55, 0x66, 0x77); 88 /// 89 /// assert_eq!(addr.is_unicast(), true); 90 /// ``` 91 #[allow(clippy::trivially_copy_pass_by_ref)] is_unicast(&self) -> bool92 pub const fn is_unicast(&self) -> bool { 93 self.0[0] & 1 == 0 94 } 95 96 /// Returns `true` if the address is multicast. 97 /// 98 /// ## Example 99 /// 100 /// ```rust 101 /// # use macaddr::MacAddr6; 102 /// let addr = MacAddr6::new(0x01, 0x00, 0x0C, 0xCC, 0xCC, 0xCC); 103 /// 104 /// assert_eq!(addr.is_multicast(), true); 105 /// ``` 106 #[allow(clippy::trivially_copy_pass_by_ref)] is_multicast(&self) -> bool107 pub const fn is_multicast(&self) -> bool { 108 self.0[0] & 1 == 1 109 } 110 111 /// Returns `true` if the address is universally administered address (UAA). 112 /// 113 /// ## Example 114 /// 115 /// ```rust 116 /// # use macaddr::MacAddr6; 117 /// let addr = MacAddr6::new(0x01, 0x00, 0x0C, 0xCC, 0xCC, 0xCC); 118 /// 119 /// assert_eq!(addr.is_universal(), true); 120 /// ``` 121 #[allow(clippy::trivially_copy_pass_by_ref)] is_universal(&self) -> bool122 pub const fn is_universal(&self) -> bool { 123 self.0[0] & 1 << 1 == 0 124 } 125 126 /// Returns `true` if the address is locally administered (LAA). 127 /// 128 /// ## Example 129 /// 130 /// ```rust 131 /// # use macaddr::MacAddr6; 132 /// let addr = MacAddr6::new(0x02, 0x00, 0x0C, 0xCC, 0xCC, 0xCC); 133 /// 134 /// assert_eq!(addr.is_local(), true); 135 /// ``` 136 #[allow(clippy::trivially_copy_pass_by_ref)] is_local(&self) -> bool137 pub const fn is_local(&self) -> bool { 138 self.0[0] & 1 << 1 == 2 139 } 140 141 /// Converts a `MacAddr6` address to a byte slice. 142 /// 143 /// ## Example 144 /// 145 /// ```rust 146 /// # use macaddr::MacAddr6; 147 /// let addr = MacAddr6::new(0xAC, 0xDE, 0x48, 0x23, 0x45, 0x67); 148 /// 149 /// assert_eq!(addr.as_bytes(), &[0xAC, 0xDE, 0x48, 0x23, 0x45, 0x67]); 150 /// ``` as_bytes(&self) -> &[u8]151 pub fn as_bytes(&self) -> &[u8] { 152 &self.0 153 } 154 155 /// Consumes `MacAddr6` address and returns raw bytes array. 156 /// 157 /// ## Example 158 /// 159 /// ```rust 160 /// # use macaddr::MacAddr6; 161 /// let addr = MacAddr6::new(0xAC, 0xDE, 0x48, 0x23, 0x45, 0x67); 162 /// 163 /// assert_eq!(addr.into_array(), [0xAC, 0xDE, 0x48, 0x23, 0x45, 0x67]); 164 /// ``` into_array(self) -> [u8; 6]165 pub const fn into_array(self) -> [u8; 6] { 166 self.0 167 } 168 } 169 170 impl FromStr for MacAddr6 { 171 type Err = parser::ParseError; 172 from_str(s: &str) -> Result<Self, Self::Err>173 fn from_str(s: &str) -> Result<Self, Self::Err> { 174 parser::Parser::new(s).read_v6_addr() 175 } 176 } 177 178 impl From<[u8; 6]> for MacAddr6 { from(bytes: [u8; 6]) -> Self179 fn from(bytes: [u8; 6]) -> Self { 180 MacAddr6(bytes) 181 } 182 } 183 184 impl AsRef<[u8]> for MacAddr6 { as_ref(&self) -> &[u8]185 fn as_ref(&self) -> &[u8] { 186 &self.0 187 } 188 } 189 190 impl AsMut<[u8]> for MacAddr6 { as_mut(&mut self) -> &mut [u8]191 fn as_mut(&mut self) -> &mut [u8] { 192 &mut self.0 193 } 194 } 195 196 /// `MacAddr6` can be displayed in different formats. 197 /// 198 /// # Example 199 /// 200 /// ``` 201 /// # use macaddr::MacAddr6; 202 /// let addr = MacAddr6::new(0xab, 0x0d, 0xef, 0x12, 0x34, 0x56); 203 /// 204 /// assert_eq!(&format!("{}", addr), "AB:0D:EF:12:34:56"); 205 /// assert_eq!(&format!("{:-}", addr), "AB-0D-EF-12-34-56"); 206 /// assert_eq!(&format!("{:#}", addr), "AB0.DEF.123.456"); 207 /// ``` 208 impl fmt::Display for MacAddr6 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result209 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 210 if f.sign_minus() { 211 f.write_fmt(format_args!( 212 "{:02X}-{:02X}-{:02X}-{:02X}-{:02X}-{:02X}", 213 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], 214 )) 215 } else if f.alternate() { 216 let p1 = u16::from(self.0[0]) * 16 + u16::from(self.0[1] / 16); 217 let p2 = u16::from(self.0[1] % 16) * 256 + u16::from(self.0[2]); 218 let p3 = u16::from(self.0[3]) * 16 + u16::from(self.0[4] / 16); 219 let p4 = u16::from(self.0[4] % 16) * 256 + u16::from(self.0[5]); 220 221 f.write_fmt(format_args!("{:03X}.{:03X}.{:03X}.{:03X}", p1, p2, p3, p4,)) 222 } else { 223 f.write_fmt(format_args!( 224 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", 225 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], 226 )) 227 } 228 } 229 } 230