ip_network_table_deps_treebitmap/
address.rs

1// Copyright 2016 Hroi Sigurdsson
2//
3// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
4// This file may not be copied, modified, or distributed except according to those terms.
5
6#[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
86/// Address trait provides methods required for storing in TreeBitmap trie datastructure.
87pub trait Address: Copy {
88    type Nibbles: AsRef<[u8]>;
89    /// Convert to string of nibbles.
90    fn nibbles(self) -> Self::Nibbles;
91    /// Convert from string of nibbles.
92    fn from_nibbles(nibbles: &[u8]) -> Self;
93    /// Returns self masked to n bits.
94    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}