system_info/data/
network.rs1#[cfg(feature = "std")]
2extern crate std;
3
4use core::fmt;
5
6#[derive(Debug, Clone, Copy)]
8pub enum Ip {
9 V4([u8; 4]),
11 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 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 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 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)]
85pub struct Address {
87 pub ip: Ip,
89 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 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}