snops_common/format/
impl_net.rs

1use std::{
2    io::{Read, Write},
3    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
4};
5
6use super::{DataFormat, DataFormatReader, DataReadError, DataWriteError};
7
8impl DataFormat for Ipv4Addr {
9    type Header = ();
10    const LATEST_HEADER: Self::Header = ();
11
12    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
13        Ok(writer.write(&self.octets())?)
14    }
15
16    fn read_data<R: Read>(reader: &mut R, _header: &Self::Header) -> Result<Self, DataReadError> {
17        let mut octets = [0u8; 4];
18        reader.read_exact(&mut octets)?;
19        Ok(Ipv4Addr::from(octets))
20    }
21}
22
23impl DataFormat for Ipv6Addr {
24    type Header = ();
25    const LATEST_HEADER: Self::Header = ();
26
27    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
28        Ok(writer.write(&self.octets())?)
29    }
30
31    fn read_data<R: Read>(reader: &mut R, _header: &Self::Header) -> Result<Self, DataReadError> {
32        let mut octets = [0u8; 16];
33        reader.read_exact(&mut octets)?;
34        Ok(Ipv6Addr::from(octets))
35    }
36}
37
38impl DataFormat for IpAddr {
39    type Header = ();
40    const LATEST_HEADER: Self::Header = ();
41
42    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
43        match self {
44            IpAddr::V4(addr) => Ok(0u8.write_data(writer)? + addr.write_data(writer)?),
45            IpAddr::V6(addr) => Ok(1u8.write_data(writer)? + addr.write_data(writer)?),
46        }
47    }
48
49    fn read_data<R: Read>(reader: &mut R, _header: &Self::Header) -> Result<Self, DataReadError> {
50        match reader.read_data(&())? {
51            0u8 => Ok(IpAddr::V4(reader.read_data(&())?)),
52            1u8 => Ok(IpAddr::V6(reader.read_data(&())?)),
53            n => Err(DataReadError::Custom(format!(
54                "invalid IpAddr discriminant: {n}"
55            ))),
56        }
57    }
58}
59
60impl DataFormat for SocketAddrV4 {
61    type Header = ();
62    const LATEST_HEADER: Self::Header = ();
63
64    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
65        Ok(self.ip().write_data(writer)? + self.port().write_data(writer)?)
66    }
67
68    fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
69        Ok(SocketAddrV4::new(
70            reader.read_data(header)?,
71            reader.read_data(header)?,
72        ))
73    }
74}
75
76impl DataFormat for SocketAddrV6 {
77    type Header = ();
78    const LATEST_HEADER: Self::Header = ();
79
80    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
81        Ok(self.ip().write_data(writer)? + self.port().write_data(writer)?)
82    }
83
84    fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
85        Ok(SocketAddrV6::new(
86            reader.read_data(header)?,
87            reader.read_data(header)?,
88            0,
89            0,
90        ))
91    }
92}
93
94impl DataFormat for SocketAddr {
95    type Header = ();
96    const LATEST_HEADER: Self::Header = ();
97
98    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
99        match self {
100            SocketAddr::V4(addr) => Ok(0u8.write_data(writer)? + addr.write_data(writer)?),
101            SocketAddr::V6(addr) => Ok(1u8.write_data(writer)? + addr.write_data(writer)?),
102        }
103    }
104
105    fn read_data<R: Read>(reader: &mut R, _header: &Self::Header) -> Result<Self, DataReadError> {
106        match reader.read_data(&())? {
107            0u8 => Ok(SocketAddr::V4(reader.read_data(&())?)),
108            1u8 => Ok(SocketAddr::V6(reader.read_data(&())?)),
109            n => Err(DataReadError::Custom(format!(
110                "invalid SocketAddr discriminant: {n}"
111            ))),
112        }
113    }
114}
115
116#[cfg(test)]
117#[rustfmt::skip]
118mod test {
119    use crate::format::DataFormat;
120    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
121
122    macro_rules! case {
123        ($name:ident, $ty:ty, $a:expr, $b:expr) => {
124            #[test]
125            fn $name() {
126                let mut data = Vec::new();
127                $a.write_data(&mut data).unwrap();
128                assert_eq!(data, &$b);
129
130                let mut reader = &data[..];
131                let read_value = <$ty>::read_data(&mut reader, &()).unwrap();
132                assert_eq!(read_value, $a);
133
134            }
135
136        };
137    }
138
139    case!(ip_localhost, Ipv4Addr, Ipv4Addr::LOCALHOST, [127, 0, 0, 1]);
140    case!(ip_v6_localhost, Ipv6Addr, "::1".parse::<Ipv6Addr>().unwrap(), [
141        0, 0, 0, 0, 0, 0, 0, 0,
142        0, 0, 0, 0, 0, 0, 0, 1,
143    ]);
144    case!(ip_v4, IpAddr, IpAddr::V4(Ipv4Addr::LOCALHOST), [0, 127, 0, 0, 1]);
145    case!(ip_v6, IpAddr, IpAddr::V6("::1".parse::<Ipv6Addr>().unwrap()), [
146        1,
147        0, 0, 0, 0, 0, 0, 0, 0,
148        0, 0, 0, 0, 0, 0, 0, 1,
149    ]);
150
151    case!(socket_v4, SocketAddrV4, SocketAddrV4::new(Ipv4Addr::LOCALHOST, 80), [
152        127, 0, 0, 1,
153        80, 0,
154    ]);
155    case!(socket_v6, SocketAddrV6, SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0), [
156        0, 0, 0, 0, 0, 0, 0, 0,
157        0, 0, 0, 0, 0, 0, 0, 1,
158        144, 31,
159    ]);
160
161    case!(socket_v4_socket, SocketAddr, SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 8080)), [
162        0,
163        127, 0, 0, 1,
164        144, 31,
165    ]);
166
167    case!(socket_v6_socket, SocketAddr, SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 8080, 0, 0)), [
168        1,
169        0, 0, 0, 0, 0, 0, 0, 0,
170        0, 0, 0, 0, 0, 0, 0, 1,
171        144, 31,
172    ]);
173}