Skip to main content

net_lattice_model/
address.rs

1use std::fmt;
2
3use net_lattice_ip::{Ipv4Address, Ipv4Network, Ipv6Address, Ipv6Network};
4
5/// An IP address of either family.
6///
7/// Domain objects (routes, interfaces, ...) that need to hold "an IP
8/// address, either family" use this instead of picking one family, since
9/// most networking state (a gateway, a resolver entry) is not inherently
10/// v4- or v6-only.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum IpAddress {
13    V4(Ipv4Address),
14    V6(Ipv6Address),
15}
16
17impl From<Ipv4Address> for IpAddress {
18    fn from(value: Ipv4Address) -> Self {
19        IpAddress::V4(value)
20    }
21}
22
23impl From<Ipv6Address> for IpAddress {
24    fn from(value: Ipv6Address) -> Self {
25        IpAddress::V6(value)
26    }
27}
28
29impl fmt::Display for IpAddress {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        match self {
32            IpAddress::V4(addr) => write!(f, "{addr}"),
33            IpAddress::V6(addr) => write!(f, "{addr}"),
34        }
35    }
36}
37
38/// An IP network of either family.
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40pub enum Network {
41    V4(Ipv4Network),
42    V6(Ipv6Network),
43}
44
45impl From<Ipv4Network> for Network {
46    fn from(value: Ipv4Network) -> Self {
47        Network::V4(value)
48    }
49}
50
51impl From<Ipv6Network> for Network {
52    fn from(value: Ipv6Network) -> Self {
53        Network::V6(value)
54    }
55}
56
57impl fmt::Display for Network {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        match self {
60            Network::V4(net) => write!(f, "{net}"),
61            Network::V6(net) => write!(f, "{net}"),
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use net_lattice_ip::{Ipv4PrefixLength, Ipv6PrefixLength};
70
71    #[test]
72    fn addresses_display_both_families() {
73        assert_eq!(
74            IpAddress::from(Ipv4Address::new(192, 0, 2, 1)).to_string(),
75            "192.0.2.1"
76        );
77        assert_eq!(
78            IpAddress::from(Ipv6Address::new([0x2001, 0xdb8, 0, 0, 0, 0, 0, 1])).to_string(),
79            "2001:db8::1"
80        );
81    }
82
83    #[test]
84    fn networks_display_both_families() {
85        assert_eq!(
86            Network::from(Ipv4Network::new(
87                Ipv4Address::new(192, 0, 2, 0),
88                Ipv4PrefixLength::new(24).expect("valid prefix"),
89            ))
90            .to_string(),
91            "192.0.2.0/24"
92        );
93        assert_eq!(
94            Network::from(Ipv6Network::new(
95                Ipv6Address::new([0x2001, 0xdb8, 0, 0, 0, 0, 0, 0]),
96                Ipv6PrefixLength::new(32).expect("valid prefix"),
97            ))
98            .to_string(),
99            "2001:db8::/32"
100        );
101    }
102}