use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AddressFamily(u8);
impl AddressFamily {
const AF_UNSPEC: u8 = 0;
const AF_INET: u8 = 2;
const AF_BRIDGE: u8 = 7;
const AF_INET6: u8 = 10;
const AF_PACKET: u8 = 17;
const AF_MPLS: u8 = 28;
pub const fn unspec() -> Self {
Self(Self::AF_UNSPEC)
}
pub const fn v4() -> Self {
Self(Self::AF_INET)
}
pub const fn ipv4() -> Self {
Self::v4()
}
pub const fn v6() -> Self {
Self(Self::AF_INET6)
}
pub const fn ipv6() -> Self {
Self::v6()
}
pub const fn bridge() -> Self {
Self(Self::AF_BRIDGE)
}
pub const fn mpls() -> Self {
Self(Self::AF_MPLS)
}
pub const fn packet() -> Self {
Self(Self::AF_PACKET)
}
pub const fn from_raw(raw: u8) -> Self {
Self(raw)
}
#[inline]
pub const fn as_u8(self) -> u8 {
self.0
}
pub const fn is_known(self) -> bool {
matches!(
self.0,
Self::AF_UNSPEC
| Self::AF_INET
| Self::AF_BRIDGE
| Self::AF_INET6
| Self::AF_PACKET
| Self::AF_MPLS
)
}
}
impl From<AddressFamily> for u8 {
fn from(f: AddressFamily) -> u8 {
f.0
}
}
impl fmt::Display for AddressFamily {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
Self::AF_UNSPEC => f.write_str("AF_UNSPEC"),
Self::AF_INET => f.write_str("AF_INET"),
Self::AF_BRIDGE => f.write_str("AF_BRIDGE"),
Self::AF_INET6 => f.write_str("AF_INET6"),
Self::AF_PACKET => f.write_str("AF_PACKET"),
Self::AF_MPLS => f.write_str("AF_MPLS"),
other => write!(f, "AF_{}", other),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn constructors_map_to_canonical_bytes() {
assert_eq!(u8::from(AddressFamily::unspec()), 0);
assert_eq!(u8::from(AddressFamily::v4()), 2);
assert_eq!(u8::from(AddressFamily::bridge()), 7);
assert_eq!(u8::from(AddressFamily::v6()), 10);
assert_eq!(u8::from(AddressFamily::packet()), 17);
assert_eq!(u8::from(AddressFamily::mpls()), 28);
}
#[test]
fn aliases_match_canonical_forms() {
assert_eq!(AddressFamily::ipv4(), AddressFamily::v4());
assert_eq!(AddressFamily::ipv6(), AddressFamily::v6());
}
#[test]
fn from_raw_roundtrip() {
for raw in [0u8, 2, 7, 10, 17, 28, 99, 255] {
assert_eq!(AddressFamily::from_raw(raw).as_u8(), raw);
}
}
#[test]
fn is_known_classification() {
assert!(AddressFamily::v4().is_known());
assert!(AddressFamily::v6().is_known());
assert!(AddressFamily::unspec().is_known());
assert!(!AddressFamily::from_raw(99).is_known());
assert!(!AddressFamily::from_raw(255).is_known());
}
#[test]
fn display_known_uses_mnemonic() {
assert_eq!(AddressFamily::v4().to_string(), "AF_INET");
assert_eq!(AddressFamily::v6().to_string(), "AF_INET6");
}
#[test]
fn display_unknown_falls_back_to_number() {
assert_eq!(AddressFamily::from_raw(99).to_string(), "AF_99");
}
}