net.rs91.89%
1
// Copyright 2025 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::str::FromStr;16
17
use serde::Deserialize;18
use serde::de::{self, Visitor};19
use serde_aco::{Help, TypedHelp};20
use zerocopy::{FromBytes, Immutable, IntoBytes};21
22
#[derive(Debug, Clone, Default, FromBytes, Immutable, IntoBytes, PartialEq, Eq)]23
#[repr(transparent)]24
pub struct MacAddr(pub [u8; 6]);25
26
#[derive(Debug)]27
pub enum Error {28
InvalidLength { len: usize },29
InvalidNumber { num: String },30
}31
32
impl FromStr for MacAddr {33
type Err = Error;34
35
fn from_str(s: &str) -> Result<Self, Self::Err> {19x36
let mut addr = [0u8; 6];19x37
let iter = s.split(':');19x38
let mut index = 0;19x39
for b_s in iter {114x40
let Ok(v) = u8::from_str_radix(b_s, 16) else {114x41
return Err(Error::InvalidNumber {3x42
num: b_s.to_owned(),3x43
});3x44
};45
if let Some(b) = addr.get_mut(index) {111x46
*b = v;108x47
};108x48
index += 1;111x49
}50
if index != 6 {16x51
return Err(Error::InvalidLength { len: index });6x52
}10x53
Ok(MacAddr(addr))10x54
}19x55
}56
57
impl Help for MacAddr {58
const HELP: TypedHelp = TypedHelp::Custom { desc: "mac-addr" };59
}60
61
struct MacAddrVisitor;62
63
impl<'de> Visitor<'de> for MacAddrVisitor {64
type Value = MacAddr;65
66
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {67
formatter.write_str("a MAC address like ea:d7:a8:e8:c6:2f")68
}69
70
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>19x71
where19x72
E: de::Error,19x73
{74
match v.parse::<MacAddr>() {19x75
Ok(v) => Ok(v),10x76
Err(Error::InvalidLength { len }) => Err(E::invalid_length(len, &"6")),6x77
Err(Error::InvalidNumber { num }) => Err(E::invalid_value(3x78
de::Unexpected::Str(num.as_str()),3x79
&"hexadecimal",3x80
)),3x81
}82
}19x83
}84
85
impl<'de> Deserialize<'de> for MacAddr {86
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>7x87
where7x88
D: de::Deserializer<'de>,7x89
{90
deserializer.deserialize_str(MacAddrVisitor)7x91
}7x92
}93
94
#[cfg(test)]95
#[path = "net_test.rs"]96
mod tests;97