macaddr/
addr6.rs

1use core::{fmt, str::FromStr};
2
3use 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))]
9pub struct MacAddr6([u8; 6]);
10
11impl 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)]
21    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    /// ```
34    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    /// ```
47    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)]
62    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)]
77    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)]
92    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)]
107    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)]
122    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)]
137    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    /// ```
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    /// ```
165    pub const fn into_array(self) -> [u8; 6] {
166        self.0
167    }
168}
169
170impl FromStr for MacAddr6 {
171    type Err = parser::ParseError;
172
173    fn from_str(s: &str) -> Result<Self, Self::Err> {
174        parser::Parser::new(s).read_v6_addr()
175    }
176}
177
178impl From<[u8; 6]> for MacAddr6 {
179    fn from(bytes: [u8; 6]) -> Self {
180        MacAddr6(bytes)
181    }
182}
183
184impl AsRef<[u8]> for MacAddr6 {
185    fn as_ref(&self) -> &[u8] {
186        &self.0
187    }
188}
189
190impl AsMut<[u8]> for MacAddr6 {
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/// ```
208impl fmt::Display for MacAddr6 {
209    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}