1use crate::error::ParseError;
17use crate::reader::SliceReader;
18use crate::traits::{ParseFrom, ParseFromWithTwoInputs};
19use ipnet::{Ipv4Net, Ipv6Net};
20use serde::{Deserialize, Serialize};
21use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
22
23pub(crate) const IPV4_LEN: u8 = 4;
24pub(crate) const IPV6_LEN: u8 = 16;
25
26#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
27pub enum Ipv4PrefixParsingError {
28 #[error("failed to parse IPv4 prefix: {0}")]
29 Parse(#[from] ParseError),
30
31 #[error("invalid prefix length {prefix_len} at byte offset {offset} (must be 0–32)")]
32 InvalidIpv4PrefixLen { offset: usize, prefix_len: u8 },
33}
34
35impl<'a> ParseFromWithTwoInputs<'a, u8, usize> for Ipv4Net {
36 type Error = Ipv4PrefixParsingError;
37
38 fn parse(
39 cur: &mut SliceReader<'a>,
40 prefix_len: u8,
41 prefix_offset: usize,
42 ) -> Result<Self, Self::Error> {
43 let prefix_size = if prefix_len >= u8::MAX - 7 {
47 u8::MAX
48 } else {
49 prefix_len.div_ceil(8)
50 };
51 let prefix = cur.read_bytes(prefix_size.min(4) as usize)?;
52 let mut network = [0; 4];
54 prefix.iter().enumerate().for_each(|(i, v)| network[i] = *v);
55 let addr = Ipv4Addr::from(network);
56 match Ipv4Net::new(addr, prefix_len) {
57 Ok(net) => Ok(net),
58 Err(_) => Err(Ipv4PrefixParsingError::InvalidIpv4PrefixLen {
59 offset: prefix_offset,
60 prefix_len,
61 }),
62 }
63 }
64}
65
66impl<'a> ParseFrom<'a> for Ipv4Net {
67 type Error = Ipv4PrefixParsingError;
68
69 fn parse(cur: &mut SliceReader<'a>) -> Result<Self, Self::Error> {
70 let offset = cur.offset();
71 let prefix_len = cur.read_u8()?;
72 ParseFromWithTwoInputs::parse(cur, prefix_len, offset)
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
77pub enum Ipv6PrefixParsingError {
78 #[error("failed to parse IPv6 prefix: {0}")]
79 Parse(#[from] ParseError),
80
81 #[error("invalid prefix length {prefix_len} at byte offset {offset} (must be 0–128)")]
82 InvalidIpv6PrefixLen { offset: usize, prefix_len: u8 },
83}
84
85impl<'a> ParseFromWithTwoInputs<'a, u8, usize> for Ipv6Net {
86 type Error = Ipv6PrefixParsingError;
87
88 fn parse(
89 cur: &mut SliceReader<'a>,
90 prefix_len: u8,
91 prefix_offset: usize,
92 ) -> Result<Self, Self::Error> {
93 let prefix_size = if prefix_len >= u8::MAX - 7 {
97 u8::MAX
98 } else {
99 prefix_len.div_ceil(8)
100 };
101 let prefix = cur.read_bytes(prefix_size.min(16) as usize)?;
102 let mut network = [0; 16];
104 prefix.iter().enumerate().for_each(|(i, v)| network[i] = *v);
105 let addr = Ipv6Addr::from(network);
106
107 match Ipv6Net::new(addr, prefix_len) {
108 Ok(net) => Ok(net),
109 Err(_) => Err(Ipv6PrefixParsingError::InvalidIpv6PrefixLen {
110 offset: prefix_offset,
111 prefix_len,
112 }),
113 }
114 }
115}
116
117impl<'a> ParseFrom<'a> for Ipv6Net {
118 type Error = Ipv6PrefixParsingError;
119
120 fn parse(cur: &mut SliceReader<'a>) -> Result<Self, Self::Error> {
121 let offset = cur.offset();
122 let prefix_len = cur.read_u8()?;
123 ParseFromWithTwoInputs::parse(cur, prefix_len, offset)
124 }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
128pub enum IpAddrParsingError {
129 #[error("IP address parsing error: {0}")]
130 Parse(#[from] ParseError),
131
132 #[error("Invalid IP address length `{length}` at offset {offset}")]
133 InvalidIpAddressLength { offset: usize, length: u8 },
134}
135
136impl<'a> ParseFrom<'a> for IpAddr {
137 type Error = IpAddrParsingError;
138 fn parse(cur: &mut SliceReader<'a>) -> Result<Self, Self::Error> {
139 let offset = cur.offset();
140 let ip_len = cur.read_u8()?;
141 match ip_len {
142 IPV4_LEN => {
143 let addr = cur.read_u32_be()?;
144 Ok(IpAddr::V4(Ipv4Addr::from(addr)))
145 }
146 IPV6_LEN => {
147 let addr = cur.read_u128_be()?;
148 Ok(IpAddr::V6(Ipv6Addr::from(addr)))
149 }
150 _ => Err(IpAddrParsingError::InvalidIpAddressLength {
151 offset,
152 length: ip_len,
153 }),
154 }
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161
162 #[test]
163 fn ipv4_slash24_octet_aligned() {
164 let data = [192, 168, 1];
165 let expected = Ok(Ipv4Net::new_assert(Ipv4Addr::new(192, 168, 1, 0), 24));
166
167 let mut r = SliceReader::new(&data);
168 let parsed = <Ipv4Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 24, 0);
169
170 assert_eq!(parsed, expected);
171 }
172
173 #[test]
174 fn ipv4_slash0_reads_no_bytes() {
175 let data: [u8; 0] = [];
176 let expected = Ok(Ipv4Net::new_assert(Ipv4Addr::UNSPECIFIED, 0));
177
178 let mut r = SliceReader::new(&data);
179 let parsed = <Ipv4Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 0, 0);
180
181 assert_eq!(parsed, expected);
182 }
183
184 #[test]
185 fn ipv4_slash32_full_address() {
186 let data = [10, 20, 30, 40];
187 let expected = Ok(Ipv4Net::new_assert(Ipv4Addr::new(10, 20, 30, 40), 32));
188
189 let mut r = SliceReader::new(&data);
190 let parsed = <Ipv4Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 32, 0);
191
192 assert_eq!(parsed, expected);
193 }
194
195 #[test]
196 fn ipv4_non_octet_boundary_slash19_consumes_three_bytes() {
197 let data = [10, 0, 32, 0xFF];
199 let expected = Ok(Ipv4Net::new_assert(Ipv4Addr::new(10, 0, 32, 0), 19));
200
201 let mut r = SliceReader::new(&data);
202 let parsed = <Ipv4Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 19, 0);
203
204 assert_eq!(parsed, expected);
205 assert_eq!(r.as_slice(), &[0xFF]);
206 }
207
208 #[test]
209 fn ipv4_prefix_len_out_of_range() {
210 let data = [1, 2, 3, 4, 5];
212 let expected = Err(Ipv4PrefixParsingError::InvalidIpv4PrefixLen {
213 offset: 7,
214 prefix_len: 33,
215 });
216
217 let mut r = SliceReader::new(&data);
218 let parsed = <Ipv4Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 33, 7);
219
220 assert_eq!(parsed, expected);
221 }
222
223 #[test]
224 fn ipv4_truncated_body() {
225 let data = [192, 168]; let expected = Err(Ipv4PrefixParsingError::Parse(ParseError::eof(0, 3, 2)));
227
228 let mut r = SliceReader::new(&data);
229 let parsed = <Ipv4Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 24, 0);
230
231 eprintln!("E: {}", expected.clone().unwrap_err());
232 assert_eq!(parsed, expected);
233 }
234
235 #[test]
236 fn ipv4_parsefrom_reads_len_then_body() {
237 let data = [24, 192, 168, 1];
238 let expected = Ok(Ipv4Net::new_assert(Ipv4Addr::new(192, 168, 1, 0), 24));
239
240 let mut r = SliceReader::new(&data);
241 let parsed = <Ipv4Net as ParseFrom<'_>>::parse(&mut r);
242
243 assert_eq!(parsed, expected);
244 assert_eq!(r.offset(), 4); }
246
247 #[test]
248 fn ipv4_parsefrom_consumes_only_its_own_entry() {
249 let data = [16, 10, 1, 8, 172];
251 let expected = Ok(Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 0, 0), 16));
252
253 let mut r = SliceReader::new(&data);
254 let parsed = <Ipv4Net as ParseFrom<'_>>::parse(&mut r);
255
256 assert_eq!(parsed, expected);
257 assert_eq!(r.as_slice(), &[8, 172]);
258 }
259
260 #[test]
261 fn ipv6_slash64_consumes_eight_bytes() {
262 let data = [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0xFF];
263 let expected = Ok(Ipv6Net::new_assert(
264 Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 0),
265 64,
266 ));
267
268 let mut r = SliceReader::new(&data);
269 let parsed = <Ipv6Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 64, 0);
270
271 assert_eq!(parsed, expected);
272 assert_eq!(r.as_slice(), &[0xFF]);
273 }
274
275 #[test]
276 fn ipv6_slash128_full_address() {
277 let data = [0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
278 let expected = Ok(Ipv6Net::new_assert(
279 Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1),
280 128,
281 ));
282
283 let mut r = SliceReader::new(&data);
284 let parsed = <Ipv6Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 128, 0);
285
286 assert_eq!(parsed, expected);
287 }
288
289 #[test]
290 fn ipv6_slash0_reads_no_bytes() {
291 let data: [u8; 0] = [];
292 let expected = Ok(Ipv6Net::new_assert(Ipv6Addr::UNSPECIFIED, 0));
293
294 let mut r = SliceReader::new(&data);
295 let parsed = <Ipv6Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 0, 0);
296
297 assert_eq!(parsed, expected);
298 }
299
300 #[test]
301 fn ipv6_prefix_len_out_of_range() {
302 let data = [0u8; 16];
303 let expected = Err(Ipv6PrefixParsingError::InvalidIpv6PrefixLen {
304 offset: 3,
305 prefix_len: 129,
306 });
307
308 let mut r = SliceReader::new(&data);
309 let parsed = <Ipv6Net as ParseFromWithTwoInputs<'_, u8, usize>>::parse(&mut r, 129, 3);
310
311 assert_eq!(parsed, expected);
312 }
313
314 #[test]
315 fn ipv6_parsefrom_reads_len_then_body() {
316 let data = [64, 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0];
317 let expected = Ok(Ipv6Net::new_assert(
318 Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 0),
319 64,
320 ));
321
322 let mut r = SliceReader::new(&data);
323 let parsed = <Ipv6Net as ParseFrom<'_>>::parse(&mut r);
324
325 assert_eq!(parsed, expected);
326 assert_eq!(r.offset(), 9); }
328
329 #[test]
330 fn ipaddr_v4() {
331 let data = [4, 10, 0, 0, 1];
332 let expected = Ok(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)));
333
334 let mut r = SliceReader::new(&data);
335 let parsed = <IpAddr as ParseFrom<'_>>::parse(&mut r);
336
337 assert_eq!(parsed, expected);
338 assert_eq!(r.offset(), 5);
339 }
340
341 #[test]
342 fn ipaddr_v6() {
343 let data = [
344 16, 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
345 ];
346 let expected = Ok(IpAddr::V6(Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1)));
347
348 let mut r = SliceReader::new(&data);
349 let parsed = <IpAddr as ParseFrom<'_>>::parse(&mut r);
350
351 assert_eq!(parsed, expected);
352 assert_eq!(r.offset(), 17);
353 }
354
355 #[test]
356 fn ipaddr_invalid_length_tag() {
357 let data = [5, 1, 2, 3, 4, 5]; let expected = Err(IpAddrParsingError::InvalidIpAddressLength {
359 offset: 0,
360 length: 5,
361 });
362
363 let mut r = SliceReader::new(&data);
364 let parsed = <IpAddr as ParseFrom<'_>>::parse(&mut r);
365
366 assert_eq!(parsed, expected);
367 }
368
369 #[test]
370 fn ipaddr_v4_truncated_body() {
371 let data = [4, 10, 0]; let expected = Err(IpAddrParsingError::Parse(ParseError::eof(1, 4, 2)));
373
374 let mut r = SliceReader::new(&data);
375 let parsed = <IpAddr as ParseFrom<'_>>::parse(&mut r);
376
377 assert_eq!(parsed, expected);
378 }
379}