commonware_codec/types/
net.rs

1//! Codec implementations for network-related types
2
3use crate::{EncodeSize, Error, FixedSize, Read, ReadExt, Write};
4use bytes::{Buf, BufMut};
5use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
6
7impl Write for Ipv4Addr {
8    #[inline]
9    fn write(&self, buf: &mut impl BufMut) {
10        self.to_bits().write(buf);
11    }
12}
13
14impl Read for Ipv4Addr {
15    type Cfg = ();
16
17    #[inline]
18    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
19        Ok(Self::from_bits(u32::read(buf)?))
20    }
21}
22
23impl FixedSize for Ipv4Addr {
24    const SIZE: usize = u32::SIZE;
25}
26
27impl Write for Ipv6Addr {
28    #[inline]
29    fn write(&self, buf: &mut impl BufMut) {
30        self.to_bits().write(buf);
31    }
32}
33
34impl Read for Ipv6Addr {
35    type Cfg = ();
36
37    #[inline]
38    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
39        Ok(Self::from_bits(u128::read(buf)?))
40    }
41}
42
43impl FixedSize for Ipv6Addr {
44    const SIZE: usize = u128::SIZE;
45}
46
47impl Write for SocketAddrV4 {
48    #[inline]
49    fn write(&self, buf: &mut impl BufMut) {
50        self.ip().write(buf);
51        self.port().write(buf);
52    }
53}
54
55impl Read for SocketAddrV4 {
56    type Cfg = ();
57
58    #[inline]
59    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
60        let ip = Ipv4Addr::read(buf)?;
61        let port = u16::read(buf)?;
62        Ok(Self::new(ip, port))
63    }
64}
65
66impl FixedSize for SocketAddrV4 {
67    const SIZE: usize = Ipv4Addr::SIZE + u16::SIZE;
68}
69
70impl Write for SocketAddrV6 {
71    #[inline]
72    fn write(&self, buf: &mut impl BufMut) {
73        self.ip().write(buf);
74        self.port().write(buf);
75    }
76}
77
78impl Read for SocketAddrV6 {
79    type Cfg = ();
80
81    #[inline]
82    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
83        let address = Ipv6Addr::read(buf)?;
84        let port = u16::read(buf)?;
85        Ok(Self::new(address, port, 0, 0))
86    }
87}
88
89impl FixedSize for SocketAddrV6 {
90    const SIZE: usize = Ipv6Addr::SIZE + u16::SIZE;
91}
92
93impl Write for IpAddr {
94    #[inline]
95    fn write(&self, buf: &mut impl BufMut) {
96        match self {
97            Self::V4(v4) => {
98                4u8.write(buf);
99                v4.write(buf);
100            }
101            Self::V6(v6) => {
102                6u8.write(buf);
103                v6.write(buf);
104            }
105        }
106    }
107}
108
109impl EncodeSize for IpAddr {
110    #[inline]
111    fn encode_size(&self) -> usize {
112        u8::SIZE
113            + match self {
114                Self::V4(_) => Ipv4Addr::SIZE,
115                Self::V6(_) => Ipv6Addr::SIZE,
116            }
117    }
118}
119
120impl Read for IpAddr {
121    type Cfg = ();
122
123    #[inline]
124    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
125        let version = u8::read(buf)?;
126        match version {
127            4 => Ok(Self::V4(Ipv4Addr::read(buf)?)),
128            6 => Ok(Self::V6(Ipv6Addr::read(buf)?)),
129            _ => Err(Error::Invalid("IpAddr", "Invalid version")),
130        }
131    }
132}
133
134// SocketAddr implementation
135impl Write for SocketAddr {
136    #[inline]
137    fn write(&self, buf: &mut impl BufMut) {
138        self.ip().write(buf);
139        self.port().write(buf);
140    }
141}
142
143impl EncodeSize for SocketAddr {
144    #[inline]
145    fn encode_size(&self) -> usize {
146        self.ip().encode_size() + u16::SIZE
147    }
148}
149
150impl Read for SocketAddr {
151    type Cfg = ();
152
153    #[inline]
154    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
155        let ip = IpAddr::read(buf)?;
156        let port = u16::read(buf)?;
157        Ok(Self::new(ip, port))
158    }
159}
160
161#[cfg(test)]
162mod test {
163    use super::*;
164    use crate::{DecodeExt, Encode};
165    use bytes::Bytes;
166
167    #[test]
168    fn test_ipv4_addr() {
169        // Test various IPv4 addresses
170        let ips = [
171            Ipv4Addr::UNSPECIFIED,
172            Ipv4Addr::LOCALHOST,
173            Ipv4Addr::new(192, 168, 1, 1),
174            Ipv4Addr::new(255, 255, 255, 255),
175        ];
176
177        for ip in ips.iter() {
178            let encoded = ip.encode();
179            assert_eq!(encoded.len(), 4);
180            let decoded = Ipv4Addr::decode(encoded).unwrap();
181            assert_eq!(*ip, decoded);
182        }
183
184        // Test insufficient data
185        let insufficient = vec![0, 0, 0]; // 3 bytes instead of 4
186        assert!(Ipv4Addr::decode(Bytes::from(insufficient)).is_err());
187    }
188
189    #[test]
190    fn test_ipv6_addr() {
191        // Test various IPv6 addresses
192        let ips = [
193            Ipv6Addr::UNSPECIFIED,
194            Ipv6Addr::LOCALHOST,
195            Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1),
196            Ipv6Addr::new(
197                0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
198            ),
199        ];
200
201        for ip in ips.iter() {
202            let encoded = ip.encode();
203            assert_eq!(encoded.len(), 16);
204            let decoded = Ipv6Addr::decode(encoded).unwrap();
205            assert_eq!(*ip, decoded);
206        }
207
208        // Test insufficient data
209        let insufficient = Bytes::from(vec![0u8; 15]); // 15 bytes instead of 16
210        assert!(Ipv6Addr::decode(insufficient).is_err());
211    }
212
213    #[test]
214    fn test_socket_addr_v4() {
215        // Test various SocketAddrV4 instances
216        let addrs = [
217            SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0),
218            SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080),
219            SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 65535),
220        ];
221
222        for addr in addrs.iter() {
223            let encoded = addr.encode();
224            assert_eq!(encoded.len(), 6);
225            let decoded = SocketAddrV4::decode(encoded).unwrap();
226            assert_eq!(*addr, decoded);
227        }
228
229        // Test insufficient data
230        let insufficient = Bytes::from(vec![0u8; 5]); // 5 bytes instead of 6
231        assert!(SocketAddrV4::decode(insufficient).is_err());
232    }
233
234    #[test]
235    fn test_socket_addr_v6() {
236        // Test various SocketAddrV6 instances
237        let addrs = [
238            SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0),
239            SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0),
240            SocketAddrV6::new(Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1), 65535, 0, 0),
241        ];
242
243        for addr in addrs.iter() {
244            let encoded = addr.encode();
245            assert_eq!(encoded.len(), 18);
246            let decoded = SocketAddrV6::decode(encoded).unwrap();
247            assert_eq!(*addr, decoded);
248        }
249
250        // Test insufficient data
251        let insufficient = Bytes::from(vec![0u8; 17]); // 17 bytes instead of 18
252        assert!(SocketAddrV6::decode(insufficient).is_err());
253    }
254
255    #[test]
256    fn test_ip_addr() {
257        // Test IpAddr::V4
258        let addr_v4 = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
259        let encoded_v4 = addr_v4.encode();
260        assert_eq!(encoded_v4.len(), 5);
261        assert_eq!(addr_v4.encode_size(), 5);
262        let decoded_v4 = IpAddr::decode(encoded_v4).unwrap();
263        assert_eq!(addr_v4, decoded_v4);
264
265        // Test IpAddr::V6
266        let addr_v6 = IpAddr::V6(Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1));
267        let encoded_v6 = addr_v6.encode();
268        assert_eq!(encoded_v6.len(), 17);
269        assert_eq!(addr_v6.encode_size(), 17);
270        let decoded_v6 = IpAddr::decode(encoded_v6).unwrap();
271        assert_eq!(addr_v6, decoded_v6);
272
273        // Test invalid version
274        let invalid_version = [5];
275        assert!(matches!(
276            IpAddr::decode(&invalid_version[..]),
277            Err(Error::Invalid(_, _))
278        ));
279
280        // Test insufficient data for V4
281        let insufficient_v4 = [4, 127, 0, 0]; // Version + 3 bytes instead of 4
282        assert!(IpAddr::decode(&insufficient_v4[..]).is_err());
283
284        // Test insufficient data for V6
285        let mut insufficient_v6 = vec![6];
286        insufficient_v6.extend_from_slice(&[0; 15]); // 15 bytes instead of 16
287        assert!(IpAddr::decode(&insufficient_v6[..]).is_err());
288    }
289
290    #[test]
291    fn test_socket_addr() {
292        // Test SocketAddr V4
293        let addr_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(196, 168, 0, 1)), 8080);
294        let encoded_v4 = addr_v4.encode();
295        assert_eq!(encoded_v4.len(), 7);
296        assert_eq!(addr_v4.encode_size(), 7);
297        let decoded_v4 = SocketAddr::decode(encoded_v4).unwrap();
298        assert_eq!(addr_v4, decoded_v4);
299
300        // Test SocketAddr V6
301        let addr_v6 = SocketAddr::new(
302            IpAddr::V6(Ipv6Addr::new(
303                0x2001, 0x0db8, 0xffff, 0x1234, 0x5678, 0x9abc, 0xdeff, 1,
304            )),
305            8080,
306        );
307        let encoded_v6 = addr_v6.encode();
308        assert_eq!(encoded_v6.len(), 19);
309        assert_eq!(addr_v6.encode_size(), 19);
310        let decoded_v6 = SocketAddr::decode(encoded_v6).unwrap();
311        assert_eq!(addr_v6, decoded_v6);
312
313        // Test invalid version
314        let invalid_version = [5]; // Neither 4 nor 6
315        assert!(matches!(
316            SocketAddr::decode(&invalid_version[..]),
317            Err(Error::Invalid(_, _))
318        ));
319
320        // Test insufficient data for V4
321        let mut insufficient_v4 = vec![4]; // Version byte
322        insufficient_v4.extend_from_slice(&[127, 0, 0, 1, 0x1f]); // IP + 1 byte of port (5 bytes total)
323        assert!(SocketAddr::decode(&insufficient_v4[..]).is_err());
324
325        // Test insufficient data for V6
326        let mut insufficient_v6 = vec![6]; // Version byte
327        insufficient_v6.extend_from_slice(&[0; 17]); // 17 bytes instead of 18
328        assert!(SocketAddr::decode(&insufficient_v6[..]).is_err());
329    }
330
331    #[test]
332    fn test_conformity() {
333        assert_eq!(Ipv4Addr::new(0, 0, 0, 0).encode(), &[0, 0, 0, 0][..]);
334        assert_eq!(Ipv4Addr::new(127, 0, 0, 1).encode(), &[127, 0, 0, 1][..]);
335        assert_eq!(
336            Ipv4Addr::new(192, 168, 1, 100).encode(),
337            &[192, 168, 1, 100][..]
338        );
339        assert_eq!(
340            Ipv4Addr::new(255, 255, 255, 255).encode(),
341            &[255, 255, 255, 255][..]
342        );
343
344        assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).encode(), &[0; 16][..]);
345        assert_eq!(
346            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).encode(),
347            &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1][..]
348        );
349        let ipv6_test: Ipv6Addr = "2001:db8::ff00:42:8329".parse().unwrap();
350        assert_eq!(
351            ipv6_test.encode(),
352            &[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0xff, 0x00, 0, 0x42, 0x83, 0x29][..]
353        );
354        assert_eq!(
355            Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff).encode(),
356            &[0xff; 16][..]
357        );
358
359        let sock_v4_1 = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 80);
360        assert_eq!(sock_v4_1.encode(), &[10, 0, 0, 1, 0x00, 0x50][..]);
361        let sock_v4_2 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 20, 30), 65535);
362        assert_eq!(sock_v4_2.encode(), &[192, 168, 20, 30, 0xFF, 0xFF][..]);
363
364        let sock_v6_1 =
365            SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
366        assert_eq!(
367            sock_v6_1.encode(),
368            &[0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x1F, 0x90][..]
369        );
370
371        let sa_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
372        assert_eq!(sa_v4.encode(), &[0x04, 127, 0, 0, 1, 0x1F, 0x90][..]);
373        let sa_v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 443);
374        assert_eq!(
375            sa_v6.encode(),
376            &[0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x01, 0xBB][..]
377        );
378    }
379
380    #[cfg(feature = "arbitrary")]
381    mod conformance {
382        use super::*;
383        use crate::conformance::CodecConformance;
384
385        commonware_conformance::conformance_tests! {
386            CodecConformance<Ipv4Addr>,
387            CodecConformance<Ipv6Addr>,
388            CodecConformance<SocketAddrV4>,
389            CodecConformance<SocketAddrV6>,
390            CodecConformance<IpAddr>,
391            CodecConformance<SocketAddr>,
392        }
393    }
394}