proxmox_api/types/
mac_addr.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(try_from = "&str", into = "String")]
12pub struct MacAddr<const B: bool>([u8; 6]);
13
14impl MacAddr<false> {
15 pub fn try_new(addr: [u8; 6]) -> Option<Self> {
16 let me = Self(addr);
17
18 (!me.ig_bit_int()).then_some(me)
19 }
20}
21
22impl TryFrom<MacAddr<true>> for MacAddr<false> {
23 type Error = ();
24
25 fn try_from(value: MacAddr<true>) -> Result<Self, Self::Error> {
26 MacAddr::<false>::try_new(value.0).ok_or(())
27 }
28}
29
30impl From<MacAddr<false>> for MacAddr<true> {
31 fn from(value: MacAddr<false>) -> Self {
32 Self(value.0)
33 }
34}
35
36impl MacAddr<true> {
37 pub fn new(addr: [u8; 6]) -> Self {
38 Self(addr)
39 }
40}
41
42impl<const B: bool> MacAddr<B> {
43 pub fn get(&self) -> [u8; 6] {
44 self.0
45 }
46
47 fn ig_bit_int(&self) -> bool {
48 (self.0[0] & 0x80) == 0x80
49 }
50
51 pub fn ig_bit(&self) -> bool {
52 debug_assert!(self.ig_bit_int());
54 B
55 }
56}
57
58impl<const B: bool> std::fmt::Display for MacAddr<B> {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 write!(
61 f,
62 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
63 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
64 )
65 }
66}
67
68impl<const B: bool> From<MacAddr<B>> for String {
69 fn from(value: MacAddr<B>) -> Self {
70 format!("{value}")
71 }
72}
73
74impl<const B: bool> TryFrom<&str> for MacAddr<B> {
75 type Error = String;
76
77 fn try_from(value: &str) -> Result<Self, Self::Error> {
78 let (count, addr) =
79 value
80 .split(':')
81 .try_fold((0usize, [0u8; 6]), |(mut idx, mut accum), input| {
82 if idx == 6 {
83 Err("Too many segments in MAC address".to_string())
84 } else if let Ok(value) = u8::from_str_radix(input, 16) {
85 accum[idx] = value;
86 idx += 1;
87 Ok((idx, accum))
88 } else {
89 Err(format!("Invalid mac address segment: {input}"))
90 }
91 })?;
92
93 let addr = MacAddr(addr);
94
95 if count != 6 {
96 Err(format!(
97 "Not enough segments in MAC address. Expected 6, got {count}"
98 ))
99 } else if !B && addr.ig_bit_int() {
100 Err(format!(
101 "MAC address type disallows IG bit, but it is set. Address: {addr}"
102 ))
103 } else {
104 Ok(addr)
105 }
106 }
107}