elicitation/verification/types/
macaddr.rs1use super::ValidationError;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
34pub struct MacAddr {
35 octets: [u8; 6],
36}
37
38impl MacAddr {
39 pub fn new(octets: [u8; 6]) -> Self {
43 Self { octets }
44 }
45
46 pub fn octets(&self) -> [u8; 6] {
48 self.octets
49 }
50
51 pub fn is_unicast(&self) -> bool {
53 (self.octets[0] & 0x01) == 0
54 }
55
56 pub fn is_multicast(&self) -> bool {
58 (self.octets[0] & 0x01) == 1
59 }
60
61 pub fn is_universal(&self) -> bool {
63 (self.octets[0] & 0x02) == 0
64 }
65
66 pub fn is_local(&self) -> bool {
68 (self.octets[0] & 0x02) == 2
69 }
70
71 pub fn is_broadcast(&self) -> bool {
73 self.octets == [0xFF; 6]
74 }
75
76 pub fn is_null(&self) -> bool {
78 self.octets == [0x00; 6]
79 }
80}
81
82pub fn is_unicast(octets: &[u8; 6]) -> bool {
88 (octets[0] & 0x01) == 0
89}
90
91pub fn is_multicast(octets: &[u8; 6]) -> bool {
93 (octets[0] & 0x01) == 1
94}
95
96pub fn is_universal(octets: &[u8; 6]) -> bool {
98 (octets[0] & 0x02) == 0
99}
100
101pub fn is_local(octets: &[u8; 6]) -> bool {
103 (octets[0] & 0x02) == 2
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
114pub struct MacUnicast(MacAddr);
115
116impl MacUnicast {
117 pub fn new(octets: [u8; 6]) -> Result<Self, ValidationError> {
123 let mac = MacAddr::new(octets);
124 if mac.is_unicast() {
125 Ok(Self(mac))
126 } else {
127 Err(ValidationError::NotUnicastMac)
128 }
129 }
130
131 pub fn get(&self) -> &MacAddr {
133 &self.0
134 }
135
136 pub fn octets(&self) -> [u8; 6] {
138 self.0.octets()
139 }
140
141 pub fn into_inner(self) -> MacAddr {
143 self.0
144 }
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
151pub struct MacMulticast(MacAddr);
152
153impl MacMulticast {
154 pub fn new(octets: [u8; 6]) -> Result<Self, ValidationError> {
160 let mac = MacAddr::new(octets);
161 if mac.is_multicast() {
162 Ok(Self(mac))
163 } else {
164 Err(ValidationError::NotMulticastMac)
165 }
166 }
167
168 pub fn get(&self) -> &MacAddr {
170 &self.0
171 }
172
173 pub fn octets(&self) -> [u8; 6] {
175 self.0.octets()
176 }
177
178 pub fn into_inner(self) -> MacAddr {
180 self.0
181 }
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
188pub struct MacUniversal(MacAddr);
189
190impl MacUniversal {
191 pub fn new(octets: [u8; 6]) -> Result<Self, ValidationError> {
197 let mac = MacAddr::new(octets);
198 if mac.is_universal() {
199 Ok(Self(mac))
200 } else {
201 Err(ValidationError::NotUniversalMac)
202 }
203 }
204
205 pub fn get(&self) -> &MacAddr {
207 &self.0
208 }
209
210 pub fn octets(&self) -> [u8; 6] {
212 self.0.octets()
213 }
214
215 pub fn into_inner(self) -> MacAddr {
217 self.0
218 }
219}
220
221#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
225pub struct MacLocal(MacAddr);
226
227impl MacLocal {
228 pub fn new(octets: [u8; 6]) -> Result<Self, ValidationError> {
234 let mac = MacAddr::new(octets);
235 if mac.is_local() {
236 Ok(Self(mac))
237 } else {
238 Err(ValidationError::NotLocalMac)
239 }
240 }
241
242 pub fn get(&self) -> &MacAddr {
244 &self.0
245 }
246
247 pub fn octets(&self) -> [u8; 6] {
249 self.0.octets()
250 }
251
252 pub fn into_inner(self) -> MacAddr {
254 self.0
255 }
256}
257
258#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_unicast_detection() {
274 let unicast = [0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E];
276 assert!(is_unicast(&unicast));
277 assert!(!is_multicast(&unicast));
278
279 let mac = MacAddr::new(unicast);
280 assert!(mac.is_unicast());
281 assert!(!mac.is_multicast());
282
283 let unicast_type = MacUnicast::new(unicast);
284 assert!(unicast_type.is_ok());
285 }
286
287 #[test]
288 fn test_multicast_detection() {
289 let multicast = [0x01, 0x00, 0x5E, 0x00, 0x00, 0x01];
291 assert!(is_multicast(&multicast));
292 assert!(!is_unicast(&multicast));
293
294 let mac = MacAddr::new(multicast);
295 assert!(mac.is_multicast());
296 assert!(!mac.is_unicast());
297
298 let multicast_type = MacMulticast::new(multicast);
299 assert!(multicast_type.is_ok());
300 }
301
302 #[test]
303 fn test_broadcast() {
304 let broadcast = [0xFF; 6];
305 let mac = MacAddr::new(broadcast);
306 assert!(mac.is_broadcast());
307 assert!(mac.is_multicast()); }
309
310 #[test]
311 fn test_null_address() {
312 let null = [0x00; 6];
313 let mac = MacAddr::new(null);
314 assert!(mac.is_null());
315 assert!(mac.is_unicast()); }
317
318 #[test]
319 fn test_universal_detection() {
320 let universal = [0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E];
322 assert!(is_universal(&universal));
323 assert!(!is_local(&universal));
324
325 let mac = MacAddr::new(universal);
326 assert!(mac.is_universal());
327 assert!(!mac.is_local());
328
329 let universal_type = MacUniversal::new(universal);
330 assert!(universal_type.is_ok());
331 }
332
333 #[test]
334 fn test_local_detection() {
335 let local = [0x02, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E];
337 assert!(is_local(&local));
338 assert!(!is_universal(&local));
339
340 let mac = MacAddr::new(local);
341 assert!(mac.is_local());
342 assert!(!mac.is_universal());
343
344 let local_type = MacLocal::new(local);
345 assert!(local_type.is_ok());
346 }
347
348 #[test]
349 fn test_unicast_rejects_multicast() {
350 let multicast = [0x01, 0x00, 0x5E, 0x00, 0x00, 0x01];
351 let result = MacUnicast::new(multicast);
352 assert!(result.is_err());
353 }
354
355 #[test]
356 fn test_multicast_rejects_unicast() {
357 let unicast = [0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E];
358 let result = MacMulticast::new(unicast);
359 assert!(result.is_err());
360 }
361
362 #[test]
363 fn test_combined_bits() {
364 let local_multicast = [0x03, 0x00, 0x00, 0x00, 0x00, 0x01];
366 let mac = MacAddr::new(local_multicast);
367 assert!(mac.is_multicast());
368 assert!(mac.is_local());
369
370 let local_unicast = [0x02, 0x00, 0x00, 0x00, 0x00, 0x01];
372 let mac = MacAddr::new(local_unicast);
373 assert!(mac.is_unicast());
374 assert!(mac.is_local());
375
376 let universal_multicast = [0x01, 0x00, 0x5E, 0x00, 0x00, 0x01];
378 let mac = MacAddr::new(universal_multicast);
379 assert!(mac.is_multicast());
380 assert!(mac.is_universal());
381 }
382}