Skip to main content

commonware_codec/types/
net.rs

1//! Codec implementations for network-related types
2
3use crate::{Buf, EncodeSize, Error, FixedSize, MaxEncodeSize, Read, ReadExt, Write};
4use bytes::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 MaxEncodeSize for IpAddr {
121    const MAX_ENCODE_SIZE: usize = u8::SIZE + Ipv6Addr::SIZE;
122}
123
124impl Read for IpAddr {
125    type Cfg = ();
126
127    #[inline]
128    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
129        let version = u8::read(buf)?;
130        match version {
131            4 => Ok(Self::V4(Ipv4Addr::read(buf)?)),
132            6 => Ok(Self::V6(Ipv6Addr::read(buf)?)),
133            _ => Err(Error::Invalid("IpAddr", "Invalid version")),
134        }
135    }
136}
137
138// SocketAddr implementation
139impl Write for SocketAddr {
140    #[inline]
141    fn write(&self, buf: &mut impl BufMut) {
142        self.ip().write(buf);
143        self.port().write(buf);
144    }
145}
146
147impl EncodeSize for SocketAddr {
148    #[inline]
149    fn encode_size(&self) -> usize {
150        self.ip().encode_size() + u16::SIZE
151    }
152}
153
154impl MaxEncodeSize for SocketAddr {
155    const MAX_ENCODE_SIZE: usize = IpAddr::MAX_ENCODE_SIZE + u16::SIZE;
156}
157
158impl Read for SocketAddr {
159    type Cfg = ();
160
161    #[inline]
162    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
163        let ip = IpAddr::read(buf)?;
164        let port = u16::read(buf)?;
165        Ok(Self::new(ip, port))
166    }
167}
168
169#[cfg(test)]
170mod test {
171    use super::*;
172    use crate::{Copying, DecodeExt, Encode};
173    use bytes::Bytes;
174
175    #[test]
176    fn test_ipv4_addr() {
177        // Test various IPv4 addresses
178        let ips = [
179            Ipv4Addr::UNSPECIFIED,
180            Ipv4Addr::LOCALHOST,
181            Ipv4Addr::new(192, 168, 1, 1),
182            Ipv4Addr::new(255, 255, 255, 255),
183        ];
184
185        for ip in ips.iter() {
186            let encoded = ip.encode();
187            assert_eq!(encoded.len(), 4);
188            let decoded = Ipv4Addr::decode(encoded).unwrap();
189            assert_eq!(*ip, decoded);
190        }
191
192        // Test insufficient data
193        let insufficient = vec![0, 0, 0]; // 3 bytes instead of 4
194        assert!(Ipv4Addr::decode(insufficient).is_err());
195    }
196
197    #[test]
198    fn test_ipv6_addr() {
199        // Test various IPv6 addresses
200        let ips = [
201            Ipv6Addr::UNSPECIFIED,
202            Ipv6Addr::LOCALHOST,
203            Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1),
204            Ipv6Addr::new(
205                0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
206            ),
207        ];
208
209        for ip in ips.iter() {
210            let encoded = ip.encode();
211            assert_eq!(encoded.len(), 16);
212            let decoded = Ipv6Addr::decode(encoded).unwrap();
213            assert_eq!(*ip, decoded);
214        }
215
216        // Test insufficient data
217        let insufficient = Bytes::from(vec![0u8; 15]); // 15 bytes instead of 16
218        assert!(Ipv6Addr::decode(insufficient).is_err());
219    }
220
221    #[test]
222    fn test_socket_addr_v4() {
223        // Test various SocketAddrV4 instances
224        let addrs = [
225            SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0),
226            SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080),
227            SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 1), 65535),
228        ];
229
230        for addr in addrs.iter() {
231            let encoded = addr.encode();
232            assert_eq!(encoded.len(), 6);
233            let decoded = SocketAddrV4::decode(encoded).unwrap();
234            assert_eq!(*addr, decoded);
235        }
236
237        // Test insufficient data
238        let insufficient = Bytes::from(vec![0u8; 5]); // 5 bytes instead of 6
239        assert!(SocketAddrV4::decode(insufficient).is_err());
240    }
241
242    #[test]
243    fn test_socket_addr_v6() {
244        // Test various SocketAddrV6 instances
245        let addrs = [
246            SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0),
247            SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0),
248            SocketAddrV6::new(Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1), 65535, 0, 0),
249        ];
250
251        for addr in addrs.iter() {
252            let encoded = addr.encode();
253            assert_eq!(encoded.len(), 18);
254            let decoded = SocketAddrV6::decode(encoded).unwrap();
255            assert_eq!(*addr, decoded);
256        }
257
258        // Test insufficient data
259        let insufficient = Bytes::from(vec![0u8; 17]); // 17 bytes instead of 18
260        assert!(SocketAddrV6::decode(insufficient).is_err());
261    }
262
263    #[test]
264    fn test_ip_addr() {
265        // Test IpAddr::V4
266        let addr_v4 = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
267        let encoded_v4 = addr_v4.encode();
268        assert_eq!(encoded_v4.len(), 5);
269        assert_eq!(addr_v4.encode_size(), 5);
270        let decoded_v4 = IpAddr::decode(encoded_v4).unwrap();
271        assert_eq!(addr_v4, decoded_v4);
272
273        // Test IpAddr::V6
274        let addr_v6 = IpAddr::V6(Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1));
275        let encoded_v6 = addr_v6.encode();
276        assert_eq!(encoded_v6.len(), 17);
277        assert_eq!(addr_v6.encode_size(), 17);
278        let decoded_v6 = IpAddr::decode(encoded_v6).unwrap();
279        assert_eq!(addr_v6, decoded_v6);
280
281        // Test invalid version
282        let invalid_version = [5];
283        assert!(matches!(
284            IpAddr::decode(Copying(&invalid_version)),
285            Err(Error::Invalid(_, _))
286        ));
287
288        // Test insufficient data for V4
289        let insufficient_v4 = [4, 127, 0, 0]; // Version + 3 bytes instead of 4
290        assert!(IpAddr::decode(Copying(&insufficient_v4)).is_err());
291
292        // Test insufficient data for V6
293        let mut insufficient_v6 = vec![6];
294        insufficient_v6.extend_from_slice(&[0; 15]); // 15 bytes instead of 16
295        assert!(IpAddr::decode(Copying(&insufficient_v6)).is_err());
296    }
297
298    #[test]
299    fn test_socket_addr() {
300        // Test SocketAddr V4
301        let addr_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(196, 168, 0, 1)), 8080);
302        let encoded_v4 = addr_v4.encode();
303        assert_eq!(encoded_v4.len(), 7);
304        assert_eq!(addr_v4.encode_size(), 7);
305        let decoded_v4 = SocketAddr::decode(encoded_v4).unwrap();
306        assert_eq!(addr_v4, decoded_v4);
307
308        // Test SocketAddr V6
309        let addr_v6 = SocketAddr::new(
310            IpAddr::V6(Ipv6Addr::new(
311                0x2001, 0x0db8, 0xffff, 0x1234, 0x5678, 0x9abc, 0xdeff, 1,
312            )),
313            8080,
314        );
315        let encoded_v6 = addr_v6.encode();
316        assert_eq!(encoded_v6.len(), 19);
317        assert_eq!(addr_v6.encode_size(), 19);
318        let decoded_v6 = SocketAddr::decode(encoded_v6).unwrap();
319        assert_eq!(addr_v6, decoded_v6);
320
321        // Test invalid version
322        let invalid_version = [5]; // Neither 4 nor 6
323        assert!(matches!(
324            SocketAddr::decode(Copying(&invalid_version)),
325            Err(Error::Invalid(_, _))
326        ));
327
328        // Test insufficient data for V4
329        let mut insufficient_v4 = vec![4]; // Version byte
330        insufficient_v4.extend_from_slice(&[127, 0, 0, 1, 0x1f]); // IP + 1 byte of port (5 bytes total)
331        assert!(SocketAddr::decode(Copying(&insufficient_v4)).is_err());
332
333        // Test insufficient data for V6
334        let mut insufficient_v6 = vec![6]; // Version byte
335        insufficient_v6.extend_from_slice(&[0; 17]); // 17 bytes instead of 18
336        assert!(SocketAddr::decode(Copying(&insufficient_v6)).is_err());
337    }
338
339    #[test]
340    fn test_conformity() {
341        assert_eq!(Ipv4Addr::new(0, 0, 0, 0).encode(), &[0, 0, 0, 0][..]);
342        assert_eq!(Ipv4Addr::new(127, 0, 0, 1).encode(), &[127, 0, 0, 1][..]);
343        assert_eq!(
344            Ipv4Addr::new(192, 168, 1, 100).encode(),
345            &[192, 168, 1, 100][..]
346        );
347        assert_eq!(
348            Ipv4Addr::new(255, 255, 255, 255).encode(),
349            &[255, 255, 255, 255][..]
350        );
351
352        assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).encode(), &[0; 16][..]);
353        assert_eq!(
354            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).encode(),
355            &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1][..]
356        );
357        let ipv6_test: Ipv6Addr = "2001:db8::ff00:42:8329".parse().unwrap();
358        assert_eq!(
359            ipv6_test.encode(),
360            &[
361                0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0xff, 0x00, 0, 0x42, 0x83, 0x29
362            ][..]
363        );
364        assert_eq!(
365            Ipv6Addr::new(
366                0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
367            )
368            .encode(),
369            &[0xff; 16][..]
370        );
371
372        let sock_v4_1 = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 80);
373        assert_eq!(sock_v4_1.encode(), &[10, 0, 0, 1, 0x00, 0x50][..]);
374        let sock_v4_2 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 20, 30), 65535);
375        assert_eq!(sock_v4_2.encode(), &[192, 168, 20, 30, 0xFF, 0xFF][..]);
376
377        let sock_v6_1 =
378            SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
379        assert_eq!(
380            sock_v6_1.encode(),
381            &[
382                0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x1F, 0x90
383            ][..]
384        );
385
386        let sa_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
387        assert_eq!(sa_v4.encode(), &[0x04, 127, 0, 0, 1, 0x1F, 0x90][..]);
388        let sa_v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 443);
389        assert_eq!(
390            sa_v6.encode(),
391            &[
392                0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x01, 0xBB
393            ][..]
394        );
395    }
396
397    #[test]
398    fn test_max_encode_size() {
399        // An IPv6 address reaches the maximum.
400        let v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), u16::MAX);
401        assert_eq!(v6.ip().encode_size(), IpAddr::MAX_ENCODE_SIZE);
402        assert_eq!(v6.encode_size(), SocketAddr::MAX_ENCODE_SIZE);
403
404        // An IPv4 address is narrower.
405        let v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), u16::MAX);
406        assert!(v4.ip().encode_size() < IpAddr::MAX_ENCODE_SIZE);
407        assert!(v4.encode_size() < SocketAddr::MAX_ENCODE_SIZE);
408    }
409
410    #[cfg(feature = "arbitrary")]
411    mod conformance {
412        use super::*;
413        use crate::conformance::CodecConformance;
414
415        commonware_conformance::conformance_tests! {
416            CodecConformance<Ipv4Addr>,
417            CodecConformance<Ipv6Addr>,
418            CodecConformance<SocketAddrV4>,
419            CodecConformance<SocketAddrV6>,
420            CodecConformance<IpAddr>,
421            CodecConformance<SocketAddr>,
422        }
423    }
424}