Skip to content

Commit 0a635fd

Browse files
authored
Merge pull request #26 from setrofim/mac-addr
Human-readable serialization for `MacAddrTypeChoice`
2 parents d06d6ab + d4a4834 commit 0a635fd

File tree

2 files changed

+128
-2
lines changed

2 files changed

+128
-2
lines changed

src/error/triples.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub enum TriplesError {
99
EmptyEnvironmentMap,
1010
EmptyMeasurementValuesMap,
1111
InvalidIpAddrType,
12+
InvalidMacAddrType,
1213
DigestAlreadyExists(String, HashAlgorithm),
1314
Unknown,
1415
}
@@ -19,6 +20,7 @@ impl std::fmt::Display for TriplesError {
1920
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2021
match self {
2122
Self::InvalidIpAddrType => write!(f, "invalid IP address type"),
23+
Self::InvalidMacAddrType => write!(f, "invalid MAC address type"),
2224
Self::EmptyMeasurementValuesMap => {
2325
write!(
2426
f,

src/triples.rs

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,9 +1835,8 @@ pub struct FlagsMap<'a> {
18351835
/// - `Deref`/`DerefMut` for direct byte manipulation
18361836
/// - `From` for construction from byte arrays
18371837
/// - `TryFrom` for fallible construction from slices
1838-
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
1838+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
18391839
#[repr(C)]
1840-
#[serde(untagged)]
18411840
pub enum MacAddrTypeChoice {
18421841
/// 48-bit EUI address
18431842
Eui48Addr(Eui48AddrType),
@@ -1885,6 +1884,24 @@ impl TryFrom<&[u8]> for MacAddrTypeChoice {
18851884
}
18861885
}
18871886

1887+
impl TryFrom<&str> for MacAddrTypeChoice {
1888+
type Error = TriplesError;
1889+
1890+
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
1891+
let parts: Vec<u8> = value
1892+
.split("-")
1893+
.map(|x| u8::from_str_radix(x, 16).map_err(|_| TriplesError::InvalidMacAddrType))
1894+
.collect::<std::result::Result<Vec<u8>, TriplesError>>()?;
1895+
1896+
let n = parts.len();
1897+
match n {
1898+
6 => Ok(Self::Eui48Addr(parts.try_into().unwrap())),
1899+
8 => Ok(Self::Eui64Addr(parts.try_into().unwrap())),
1900+
_ => Err(TriplesError::InvalidMacAddrType),
1901+
}
1902+
}
1903+
}
1904+
18881905
impl AsRef<[u8]> for MacAddrTypeChoice {
18891906
fn as_ref(&self) -> &[u8] {
18901907
match self {
@@ -1923,6 +1940,62 @@ impl DerefMut for MacAddrTypeChoice {
19231940
}
19241941
}
19251942

1943+
impl Display for MacAddrTypeChoice {
1944+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1945+
match self {
1946+
Self::Eui48Addr(addr) => write!(
1947+
f,
1948+
"{:02X?}-{:02X?}-{:02X?}-{:02X?}-{:02X?}-{:02X?}",
1949+
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
1950+
),
1951+
Self::Eui64Addr(addr) => write!(
1952+
f,
1953+
"{:02X?}-{:02X?}-{:02X?}-{:02X?}-{:02X?}-{:02X?}-{:02X?}-{:02X?}",
1954+
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]
1955+
),
1956+
}
1957+
}
1958+
}
1959+
1960+
impl Serialize for MacAddrTypeChoice {
1961+
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1962+
where
1963+
S: Serializer,
1964+
{
1965+
let is_human_readable = serializer.is_human_readable();
1966+
1967+
if is_human_readable {
1968+
self.to_string().serialize(serializer)
1969+
} else {
1970+
match self {
1971+
Self::Eui48Addr(octets) => serializer.serialize_bytes(octets.as_slice()),
1972+
Self::Eui64Addr(octets) => serializer.serialize_bytes(octets.as_slice()),
1973+
}
1974+
}
1975+
}
1976+
}
1977+
1978+
impl<'de> Deserialize<'de> for MacAddrTypeChoice {
1979+
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1980+
where
1981+
D: Deserializer<'de>,
1982+
{
1983+
let is_human_readable = deserializer.is_human_readable();
1984+
1985+
if is_human_readable {
1986+
String::deserialize(deserializer)?
1987+
.as_str()
1988+
.try_into()
1989+
.map_err(de::Error::custom)
1990+
} else {
1991+
Vec::<u8>::deserialize(deserializer)?
1992+
.as_slice()
1993+
.try_into()
1994+
.map_err(de::Error::custom)
1995+
}
1996+
}
1997+
}
1998+
19261999
/// 48-bit MAC address type
19272000
pub type Eui48AddrType = [u8; 6];
19282001
/// 64-bit MAC address type
@@ -3562,4 +3635,55 @@ mod test {
35623635

35633636
assert_eq!(addr_de, addr);
35643637
}
3638+
3639+
#[test]
3640+
fn test_mac_addr_serde() {
3641+
let addr = MacAddrTypeChoice::Eui48Addr([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
3642+
3643+
let json = serde_json::to_string(&addr).unwrap();
3644+
3645+
assert_eq!("\"01-02-03-04-05-06\"", json);
3646+
3647+
let addr_de: MacAddrTypeChoice = serde_json::from_str(&json).unwrap();
3648+
3649+
assert_eq!(addr_de, addr);
3650+
3651+
let mut actual: Vec<u8> = vec![];
3652+
ciborium::into_writer(&addr, &mut actual).unwrap();
3653+
3654+
let expected = vec![
3655+
0x46, // bstr(6),
3656+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
3657+
];
3658+
3659+
assert_eq!(actual, expected);
3660+
3661+
let addr_de: MacAddrTypeChoice = ciborium::from_reader(expected.as_slice()).unwrap();
3662+
3663+
assert_eq!(addr_de, addr);
3664+
3665+
let addr = MacAddrTypeChoice::Eui64Addr([0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x20]);
3666+
3667+
let json = serde_json::to_string(&addr).unwrap();
3668+
3669+
assert_eq!("\"0A-0B-0C-0D-0E-0F-10-20\"", json);
3670+
3671+
let addr_de: MacAddrTypeChoice = serde_json::from_str(&json).unwrap();
3672+
3673+
assert_eq!(addr_de, addr);
3674+
3675+
let mut actual: Vec<u8> = vec![];
3676+
ciborium::into_writer(&addr, &mut actual).unwrap();
3677+
3678+
let expected = vec![
3679+
0x48, // bstr(8),
3680+
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x20,
3681+
];
3682+
3683+
assert_eq!(actual, expected);
3684+
3685+
let addr_de: MacAddrTypeChoice = ciborium::from_reader(expected.as_slice()).unwrap();
3686+
3687+
assert_eq!(addr_de, addr);
3688+
}
35653689
}

0 commit comments

Comments
 (0)