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 7 use std::error::Error; 8 use std::fmt; 9 use std::net::{Ipv4Addr, Ipv6Addr}; 10 use std::str::FromStr; 11 12 use ipnet::{IpNet, Ipv4Net, Ipv6Net}; 13 14 pub struct Parser<'a> { 15 // parsing as ASCII, so can use byte array 16 s: &'a [u8], 17 pos: usize, 18 } 19 20 impl<'a> Parser<'a> { new(s: &'a str) -> Parser<'a>21 fn new(s: &'a str) -> Parser<'a> { 22 Parser { 23 s: s.as_bytes(), 24 pos: 0, 25 } 26 } 27 is_eof(&self) -> bool28 fn is_eof(&self) -> bool { 29 self.pos == self.s.len() 30 } 31 32 // Commit only if parser returns Some read_atomically<T, F>(&mut self, cb: F) -> Option<T> where F: FnOnce(&mut Parser) -> Option<T>,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 read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where F: FnOnce(&mut Parser) -> Option<T>,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 read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>]) -> Option<T>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 read_seq_3<A, B, C, PA, PB, PC>(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)> where PA: FnOnce(&mut Parser) -> Option<A>, PB: FnOnce(&mut Parser) -> Option<B>, PC: FnOnce(&mut Parser) -> Option<C>,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 read_char(&mut self) -> Option<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 read_given_char(&mut self, c: char) -> Option<char>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 read_digit(&mut self, radix: u8) -> Option<u8>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 read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32>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 read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32>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 read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr>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 read_ipv4_addr(&mut self) -> Option<Ipv4Addr>177 fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> { 178 self.read_atomically(|p| p.read_ipv4_addr_impl()) 179 } 180 read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr>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 read_ipv6_addr(&mut self) -> Option<Ipv6Addr>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 read_ipv4_net(&mut self) -> Option<Ipv4Net>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 read_ipv6_net(&mut self) -> Option<Ipv6Net>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 read_ip_net(&mut self) -> Option<IpNet>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 295 impl FromStr for IpNet { 296 type Err = AddrParseError; from_str(s: &str) -> Result<IpNet, AddrParseError>297 fn from_str(s: &str) -> Result<IpNet, AddrParseError> { 298 match Parser::new(s).read_till_eof(|p| p.read_ip_net()) { 299 Some(s) => Ok(s), 300 None => Err(AddrParseError(())) 301 } 302 } 303 } 304 305 impl FromStr for Ipv4Net { 306 type Err = AddrParseError; from_str(s: &str) -> Result<Ipv4Net, AddrParseError>307 fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> { 308 match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) { 309 Some(s) => Ok(s), 310 None => Err(AddrParseError(())) 311 } 312 } 313 } 314 315 impl FromStr for Ipv6Net { 316 type Err = AddrParseError; from_str(s: &str) -> Result<Ipv6Net, AddrParseError>317 fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> { 318 match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) { 319 Some(s) => 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)] 337 pub struct AddrParseError(()); 338 339 impl fmt::Display for AddrParseError { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result340 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 341 fmt.write_str("invalid IP address syntax") 342 } 343 } 344 345 impl Error for AddrParseError {} 346