system_info/data/
network.rs

1#[cfg(feature = "std")]
2extern crate std;
3
4use core::fmt;
5
6///IP address
7#[derive(Debug, Clone, Copy)]
8pub enum Ip {
9    ///IP version 4
10    V4([u8; 4]),
11    ///IP version 6
12    V6([u16; 8]),
13}
14
15#[inline(always)]
16const fn is_v4_unspecified(ip: [u8; 4]) -> bool {
17    u32::from_ne_bytes(ip) == 0
18}
19
20#[inline(always)]
21const fn is_v4_loopback(ip: [u8; 4]) -> bool {
22    ip[0] == 127
23}
24
25#[inline(always)]
26const fn is_v6_unspecified(ip: [u16; 8]) -> bool {
27    ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0
28}
29
30#[inline(always)]
31const fn is_v6_loopback(ip: [u16; 8]) -> bool {
32    ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 1
33}
34
35impl Ip {
36    #[cfg(feature = "std")]
37    ///Converts to `std` `IpAddr`
38    ///
39    ///Requires `std` feature.
40    pub const fn to_std(&self) -> std::net::IpAddr {
41        match self {
42            Ip::V4(addr) => std::net::IpAddr::V4(std::net::Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3])),
43            Ip::V6(addr) => std::net::IpAddr::V6(std::net::Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]))
44        }
45    }
46
47    ///Returns whether it is `unspecified` IP (namely zero IP).
48    pub const fn is_unspecified(&self) -> bool {
49        match self {
50            Ip::V4(addr) => is_v4_unspecified(*addr),
51            Ip::V6(addr) => is_v6_unspecified(*addr),
52        }
53    }
54
55    ///Returns whether it is `loopback` IP.
56    pub const fn is_loopback(&self) -> bool {
57        match self {
58            Ip::V4(addr) => is_v4_loopback(*addr),
59            Ip::V6(addr) => is_v6_loopback(*addr),
60        }
61    }
62}
63
64impl fmt::Display for Ip {
65    #[inline(always)]
66    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
67        match self {
68            Ip::V4(addr) => {
69                fmt.write_fmt(format_args!("{}.{}.{}.{}", addr[0], addr[1], addr[2], addr[3]))
70            },
71            Ip::V6(addr) => {
72                if is_v6_unspecified(*addr) {
73                    fmt.write_str("::")
74                } else if is_v6_loopback(*addr) {
75                    fmt.write_str("::1")
76                } else {
77                    fmt.write_fmt(format_args!("{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]))
78                }
79            },
80        }
81    }
82}
83
84#[derive(Debug, Clone, Copy)]
85///Socket's address.
86pub struct Address {
87    ///Ip address.
88    pub ip: Ip,
89    ///Network address prefix.
90    pub prefix: u8,
91}
92
93impl fmt::Display for Address {
94    #[inline(always)]
95    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
96        fmt::Display::fmt(&self.ip, fmt)
97    }
98}
99
100impl Address {
101    #[allow(unused)]
102    ///Calculates netmask from prefix.
103    pub const fn net_mask(&self) -> Ip {
104        match self.ip {
105            Ip::V4(_) => {
106                debug_assert!(self.prefix <= 32, "IPv4 prefix cannot be above 32");
107                let ip = match self.prefix {
108                    0 => 0u32,
109                    prefix => u32::max_value().wrapping_shl(32u32.wrapping_sub(prefix as u32)),
110                }.to_be_bytes();
111
112                Ip::V4(ip)
113            },
114            Ip::V6(_) => {
115                debug_assert!(self.prefix <= 128, "IPv6 prefix cannot be above 128");
116                let ip = match self.prefix {
117                    0 => 0u128,
118                    prefix => u128::max_value().wrapping_shl(128u32.wrapping_sub(prefix as u32)),
119                }.to_be_bytes();
120
121                let ip = [
122                    u16::from_ne_bytes([ip[0], ip[1]]),
123                    u16::from_ne_bytes([ip[2], ip[3]]),
124                    u16::from_ne_bytes([ip[4], ip[5]]),
125                    u16::from_ne_bytes([ip[6], ip[7]]),
126                    u16::from_ne_bytes([ip[8], ip[9]]),
127                    u16::from_ne_bytes([ip[10], ip[11]]),
128                    u16::from_ne_bytes([ip[12], ip[13]]),
129                    u16::from_ne_bytes([ip[14], ip[15]]),
130                ];
131
132                Ip::V6(ip)
133            }
134        }
135    }
136}