1#[cfg(not(feature = "alloc"))]
7use std::net::{Ipv4Addr, Ipv6Addr};
8#[cfg(feature = "alloc")]
9pub mod addr {
10 #[derive(Copy, Clone)]
11 pub struct Ipv4Addr([u8; 4]);
12 impl Ipv4Addr {
13 pub fn new(a1: u8, a2: u8, a3: u8, a4: u8) -> Self {
14 Ipv4Addr([a1, a2, a3, a4])
15 }
16
17 pub fn from(num: u32) -> Self {
18 Ipv4Addr([
19 (num >> 24) as u8,
20 (num >> 16) as u8,
21 (num >> 8) as u8,
22 num as u8,
23 ])
24 }
25
26 pub fn octets(&self) -> [u8; 4] {
27 self.0
28 }
29 }
30 impl ::std::convert::From<Ipv4Addr> for u32 {
31 fn from(a: Ipv4Addr) -> u32 {
32 (a.0[0] as u32) << 24
33 | (a.0[1] as u32) << 16
34 | (a.0[2] as u32) << 8
35 | (a.0[3] as u32) << 0
36 }
37 }
38
39 #[derive(Copy, Clone)]
40 pub struct Ipv6Addr([u8; 16]);
41
42 impl Ipv6Addr {
43 pub fn new(a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16, a8: u16) -> Self {
44 Ipv6Addr([
45 (a1 >> 8) as u8,
46 a1 as u8,
47 (a2 >> 8) as u8,
48 a2 as u8,
49 (a3 >> 8) as u8,
50 a3 as u8,
51 (a4 >> 8) as u8,
52 a4 as u8,
53 (a5 >> 8) as u8,
54 a5 as u8,
55 (a6 >> 8) as u8,
56 a6 as u8,
57 (a7 >> 8) as u8,
58 a7 as u8,
59 (a8 >> 8) as u8,
60 a8 as u8,
61 ])
62 }
63
64 pub fn octets(&self) -> [u8; 16] {
65 self.0
66 }
67
68 pub fn segments(&self) -> [u16; 8] {
69 [
70 (self.0[0] as u16) << 8 | (self.0[1] as u16),
71 (self.0[2] as u16) << 8 | (self.0[3] as u16),
72 (self.0[4] as u16) << 8 | (self.0[5] as u16),
73 (self.0[6] as u16) << 8 | (self.0[7] as u16),
74 (self.0[8] as u16) << 8 | (self.0[9] as u16),
75 (self.0[10] as u16) << 8 | (self.0[11] as u16),
76 (self.0[12] as u16) << 8 | (self.0[13] as u16),
77 (self.0[14] as u16) << 8 | (self.0[15] as u16),
78 ]
79 }
80 }
81}
82
83#[cfg(feature = "alloc")]
84use self::addr::*;
85
86pub trait Address: Copy {
88 type Nibbles: AsRef<[u8]>;
89 fn nibbles(self) -> Self::Nibbles;
91 fn from_nibbles(nibbles: &[u8]) -> Self;
93 fn mask(self, masklen: u32) -> Self;
95}
96
97impl Address for Ipv4Addr {
98 type Nibbles = [u8; 8];
99
100 fn nibbles(self) -> Self::Nibbles {
101 let mut ret: Self::Nibbles = [0; 8];
102 let bytes: [u8; 4] = self.octets();
103 for (i, byte) in bytes.iter().enumerate() {
104 ret[i * 2] = byte >> 4;
105 ret[i * 2 + 1] = byte & 0xf;
106 }
107 ret
108 }
109
110 fn from_nibbles(nibbles: &[u8]) -> Self {
111 let mut ret: [u8; 4] = [0; 4];
112 for (i, nibble) in nibbles.iter().enumerate().take(ret.len() * 2) {
113 match i % 2 {
114 0 => {
115 ret[i / 2] = *nibble << 4;
116 }
117 _ => {
118 ret[i / 2] |= *nibble;
119 }
120 }
121 }
122 Self::new(ret[0], ret[1], ret[2], ret[3])
123 }
124
125 fn mask(self, masklen: u32) -> Self {
126 debug_assert!(masklen <= 32);
127 let ip = u32::from(self);
128 let masked = match masklen {
129 0 => 0,
130 n => ip & (!0 << (32 - n)),
131 };
132 Ipv4Addr::from(masked)
133 }
134}
135
136impl Address for Ipv6Addr {
137 type Nibbles = [u8; 32];
138
139 fn nibbles(self) -> Self::Nibbles {
140 let mut ret: Self::Nibbles = [0; 32];
141 let bytes: [u8; 16] = self.octets();
142 for (i, byte) in bytes.iter().enumerate() {
143 ret[i * 2] = byte >> 4;
144 ret[i * 2 + 1] = byte & 0xf;
145 }
146 ret
147 }
148
149 fn from_nibbles(nibbles: &[u8]) -> Self {
150 let mut ret: [u16; 8] = [0; 8];
151 for (i, nibble) in nibbles.iter().enumerate().take(ret.len() * 4) {
152 match i % 4 {
153 0 => {
154 ret[i / 4] |= (*nibble as u16) << 12;
155 }
156 1 => {
157 ret[i / 4] |= (*nibble as u16) << 8;
158 }
159 2 => {
160 ret[i / 4] |= (*nibble as u16) << 4;
161 }
162 _ => {
163 ret[i / 4] |= *nibble as u16;
164 }
165 }
166 }
167 Self::new(
168 ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7],
169 )
170 }
171
172 fn mask(self, masklen: u32) -> Self {
173 debug_assert!(masklen <= 128);
174 let mut ret = self.segments();
175 for i in ((masklen + 15) / 16)..8 {
176 ret[i as usize] = 0;
177 }
178 if masklen % 16 != 0 {
179 ret[masklen as usize / 16] &= !0 << (16 - (masklen % 16));
180 }
181 Self::new(
182 ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7],
183 )
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use std::net::{Ipv4Addr, Ipv6Addr};
191 use std::str::FromStr;
192
193 #[test]
194 fn address_ipv4_mask() {
195 let ip = Ipv4Addr::new(1, 2, 3, 4);
196 assert_eq!(ip.mask(0), Ipv4Addr::new(0, 0, 0, 0));
197 assert_eq!(ip.mask(24), Ipv4Addr::new(1, 2, 3, 0));
198 assert_eq!(ip.mask(23), Ipv4Addr::new(1, 2, 2, 0));
199 assert_eq!(ip.mask(32), Ipv4Addr::new(1, 2, 3, 4));
200 }
201
202 #[test]
203 fn address_ipv6_mask() {
204 let ip = Ipv6Addr::from_str("2001:db8:aaaa:bbbb:cccc:dddd:eeee:ffff").unwrap();
205 let expected1 = Ipv6Addr::from_str("2001:db8:aaaa::").unwrap();
206 let expected2 = Ipv6Addr::from_str("2001:db8:aaaa:bbbb:cccc:dddd::").unwrap();
207 let expected3 = Ipv6Addr::from_str("::").unwrap();
208 let expected4 = Ipv6Addr::from_str("2000::").unwrap();
209 assert_ne!(ip.mask(46), expected1);
210 assert_eq!(ip.mask(47), expected1);
211 assert_eq!(ip.mask(48), expected1);
212 assert_ne!(ip.mask(49), expected1);
213 assert_eq!(ip.mask(96), expected2);
214 assert_eq!(ip.mask(0), expected3);
215 assert_ne!(ip.mask(2), expected4);
216 assert_eq!(ip.mask(3), expected4);
217 assert_eq!(ip.mask(4), expected4);
218 assert_eq!(ip.mask(15), expected4);
219 assert_ne!(ip.mask(16), expected4);
220 assert_eq!(ip.mask(128), ip);
221 }
222
223 #[test]
224 fn address_ipv4_nibbles() {
225 let ip = Ipv4Addr::from(0x12345678);
226 assert_eq!(ip.nibbles(), [1, 2, 3, 4, 5, 6, 7, 8]);
227 }
228
229 #[test]
230 fn address_ipv6_nibbles() {
231 let ip = Ipv6Addr::from_str("2001:db8:aaaa:bbbb:cccc:dddd:eeee:ffff").unwrap();
232 assert_eq!(
233 ip.nibbles(),
234 [
235 0x2, 0x0, 0x0, 0x1, 0x0, 0xd, 0xb, 0x8, 0xa, 0xa, 0xa, 0xa, 0xb, 0xb, 0xb, 0xb,
236 0xc, 0xc, 0xc, 0xc, 0xd, 0xd, 0xd, 0xd, 0xe, 0xe, 0xe, 0xe, 0xf, 0xf, 0xf, 0xf,
237 ]
238 );
239 }
240
241 #[test]
242 fn address_ipv4_from_nibbles() {
243 let ip: Ipv4Addr = Address::from_nibbles(&[1, 2, 3, 4, 5, 6, 7, 8]);
244 assert_eq!(ip.octets(), [0x12, 0x34, 0x56, 0x78]);
245 }
246
247 #[test]
248 fn address_ipv4_from_nibbles_short() {
249 let ip: Ipv4Addr = Address::from_nibbles(&[]);
250 assert_eq!(ip.octets(), [0, 0, 0, 0]);
251 }
252
253 #[test]
254 fn address_ipv4_from_nibbles_long() {
255 let ip: Ipv4Addr = Address::from_nibbles(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
256 assert_eq!(ip.octets(), [0x12, 0x34, 0x56, 0x78]);
257 }
258
259 #[test]
260 fn address_ipv6_from_nibbles() {
261 let ip: Ipv6Addr = Address::from_nibbles(&[
262 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7,
263 6, 5, 4, 3, 2, 1, 0,
264 ]);
265 let expected = Ipv6Addr::new(
266 0x123, 0x4567, 0x89ab, 0xcdef, 0xfedc, 0xba98, 0x7654, 0x3210,
267 );
268 assert_eq!(ip, expected);
269 }
270}