1//! A private parser implementation of IPv4 and IPv6 network addresses.
2//!
3//! The existing `std::net::parser` module cannot be extended because it
4//! is private. It is copied and extended here with methods for parsing
5//! IP network addresses.
6
7use std::error::Error;
8use std::fmt;
9use std::net::{Ipv4Addr, Ipv6Addr};
10use std::str::FromStr;
11
12use crate::ipnet::{IpNet, Ipv4Net, Ipv6Net};
13
14pub struct Parser<'a> {
15 // parsing as ASCII, so can use byte array
16 s: &'a [u8],
17 pos: usize,
18}
19
20impl<'a> Parser<'a> {
21 fn new(s: &'a str) -> Parser<'a> {
22 Parser {
23 s: s.as_bytes(),
24 pos: 0,
25 }
26 }
27
28 fn is_eof(&self) -> bool {
29 self.pos == self.s.len()
30 }
31
32 // Commit only if parser returns Some
33 fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
34 F: FnOnce(&mut Parser) -> Option<T>,
35 {
36 let pos = self.pos;
37 let r = cb(self);
38 if r.is_none() {
39 self.pos = pos;
40 }
41 r
42 }
43
44 // Commit only if parser read till EOF
45 fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
46 F: FnOnce(&mut Parser) -> Option<T>,
47 {
48 self.read_atomically(move |p| {
49 match cb(p) {
50 Some(x) => if p.is_eof() {Some(x)} else {None},
51 None => None,
52 }
53 })
54 }
55
56 // Return result of first successful parser
57 fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
58 -> Option<T> {
59 for pf in parsers {
60 if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
61 return Some(r);
62 }
63 }
64 None
65 }
66
67 // Apply 3 parsers sequentially
68 fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
69 pa: PA,
70 pb: PB,
71 pc: PC)
72 -> Option<(A, B, C)> where
73 PA: FnOnce(&mut Parser) -> Option<A>,
74 PB: FnOnce(&mut Parser) -> Option<B>,
75 PC: FnOnce(&mut Parser) -> Option<C>,
76 {
77 self.read_atomically(move |p| {
78 let a = pa(p);
79 let b = if a.is_some() { pb(p) } else { None };
80 let c = if b.is_some() { pc(p) } else { None };
81 match (a, b, c) {
82 (Some(a), Some(b), Some(c)) => Some((a, b, c)),
83 _ => None
84 }
85 })
86 }
87
88 // Read next char
89 fn read_char(&mut self) -> Option<char> {
90 if self.is_eof() {
91 None
92 } else {
93 let r = self.s[self.pos] as char;
94 self.pos += 1;
95 Some(r)
96 }
97 }
98
99 // Return char and advance iff next char is equal to requested
100 fn read_given_char(&mut self, c: char) -> Option<char> {
101 self.read_atomically(|p| {
102 match p.read_char() {
103 Some(next) if next == c => Some(next),
104 _ => None,
105 }
106 })
107 }
108
109 // Read digit
110 fn read_digit(&mut self, radix: u8) -> Option<u8> {
111 fn parse_digit(c: char, radix: u8) -> Option<u8> {
112 let c = c as u8;
113 // assuming radix is either 10 or 16
114 if c >= b'0' && c <= b'9' {
115 Some(c - b'0')
116 } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
117 Some(c - b'a' + 10)
118 } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
119 Some(c - b'A' + 10)
120 } else {
121 None
122 }
123 }
124
125 self.read_atomically(|p| {
126 p.read_char().and_then(|c| parse_digit(c, radix))
127 })
128 }
129
130 fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
131 let mut r = 0;
132 let mut digit_count = 0;
133 loop {
134 match self.read_digit(radix) {
135 Some(d) => {
136 r = r * (radix as u32) + (d as u32);
137 digit_count += 1;
138 if digit_count > max_digits || r >= upto {
139 return None
140 }
141 }
142 None => {
143 if digit_count == 0 {
144 return None
145 } else {
146 return Some(r)
147 }
148 }
149 };
150 }
151 }
152
153 // Read number, failing if max_digits of number value exceeded
154 fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
155 self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
156 }
157
158 fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
159 let mut bs = [0; 4];
160 let mut i = 0;
161 while i < 4 {
162 if i != 0 && self.read_given_char('.').is_none() {
163 return None;
164 }
165
166 let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
167 match octet {
168 Some(d) => bs[i] = d,
169 None => return None,
170 };
171 i += 1;
172 }
173 Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
174 }
175
176 // Read IPv4 address
177 fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
178 self.read_atomically(|p| p.read_ipv4_addr_impl())
179 }
180
181 fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
182 fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
183 assert!(head.len() + tail.len() <= 8);
184 let mut gs = [0; 8];
185 gs[..head.len()].copy_from_slice(head);
186 gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
187 Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
188 }
189
190 fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
191 -> (usize, bool) {
192 let mut i = 0;
193 while i < limit {
194 if i < limit - 1 {
195 let ipv4 = p.read_atomically(|p| {
196 if i == 0 || p.read_given_char(':').is_some() {
197 p.read_ipv4_addr()
198 } else {
199 None
200 }
201 });
202 if let Some(v4_addr) = ipv4 {
203 let octets = v4_addr.octets();
204 groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
205 groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
206 return (i + 2, true);
207 }
208 }
209
210 let group = p.read_atomically(|p| {
211 if i == 0 || p.read_given_char(':').is_some() {
212 p.read_number(16, 4, 0x10000).map(|n| n as u16)
213 } else {
214 None
215 }
216 });
217 match group {
218 Some(g) => groups[i] = g,
219 None => return (i, false)
220 }
221 i += 1;
222 }
223 (i, false)
224 }
225
226 let mut head = [0; 8];
227 let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
228
229 if head_size == 8 {
230 return Some(Ipv6Addr::new(
231 head[0], head[1], head[2], head[3],
232 head[4], head[5], head[6], head[7]))
233 }
234
235 // IPv4 part is not allowed before `::`
236 if head_ipv4 {
237 return None
238 }
239
240 // read `::` if previous code parsed less than 8 groups
241 if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
242 return None;
243 }
244
245 let mut tail = [0; 8];
246 let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
247 Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
248 }
249
250 fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
251 self.read_atomically(|p| p.read_ipv6_addr_impl())
252 }
253
254 /* Additions for IpNet below. */
255
256 // Read IPv4 network
257 fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
258 let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
259 let slash = |p: &mut Parser| p.read_given_char('/');
260 let prefix_len = |p: &mut Parser| {
261 p.read_number(10, 2, 33).map(|n| n as u8)
262 };
263
264 self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
265 let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
266 Ipv4Net::new(ip, prefix_len).unwrap()
267 })
268 }
269
270 // Read Ipv6 network
271 fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
272 let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
273 let slash = |p: &mut Parser| p.read_given_char('/');
274 let prefix_len = |p: &mut Parser| {
275 p.read_number(10, 3, 129).map(|n| n as u8)
276 };
277
278 self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
279 let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
280 Ipv6Net::new(ip, prefix_len).unwrap()
281 })
282 }
283
284 fn read_ip_net(&mut self) -> Option<IpNet> {
285 let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
286 let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
287 self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
288 }
289
290 /* Additions for IpNet above. */
291}
292
293/* Additions for IpNet below. */
294
295impl FromStr for IpNet {
296 type Err = AddrParseError;
297 fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
298 match Parser::new(s).read_till_eof(|p: &mut Parser<'_>| p.read_ip_net()) {
299 Some(s: IpNet) => Ok(s),
300 None => Err(AddrParseError(()))
301 }
302 }
303}
304
305impl FromStr for Ipv4Net {
306 type Err = AddrParseError;
307 fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
308 match Parser::new(s).read_till_eof(|p: &mut Parser<'_>| p.read_ipv4_net()) {
309 Some(s: Ipv4Net) => Ok(s),
310 None => Err(AddrParseError(()))
311 }
312 }
313}
314
315impl FromStr for Ipv6Net {
316 type Err = AddrParseError;
317 fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
318 match Parser::new(s).read_till_eof(|p: &mut Parser<'_>| p.read_ipv6_net()) {
319 Some(s: Ipv6Net) => Ok(s),
320 None => Err(AddrParseError(()))
321 }
322 }
323}
324
325/* Additions for IpNet above. */
326
327/// An error which can be returned when parsing an IP network address.
328///
329/// This error is used as the error type for the [`FromStr`] implementation for
330/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
331///
332/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
333/// [`IpNet`]: enum.IpNet.html
334/// [`Ipv4Net`]: struct.Ipv4Net.html
335/// [`Ipv6Net`]: struct.Ipv6Net.html
336#[derive(Debug, Clone, PartialEq, Eq)]
337pub struct AddrParseError(());
338
339impl fmt::Display for AddrParseError {
340 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
341 fmt.write_str(data:"invalid IP address syntax")
342 }
343}
344
345impl Error for AddrParseError {}
346