1 | //! A private parser implementation of IPv4, IPv6, and socket addresses. |
2 | //! |
3 | //! This module is "publicly exported" through the `FromStr` implementations |
4 | //! below. |
5 | |
6 | use crate::convert::TryInto; |
7 | use crate::error::Error; |
8 | use crate::fmt; |
9 | use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; |
10 | use crate::str::FromStr; |
11 | |
12 | trait ReadNumberHelper: Sized { |
13 | const ZERO: Self; |
14 | fn checked_mul(&self, other: u32) -> Option<Self>; |
15 | fn checked_add(&self, other: u32) -> Option<Self>; |
16 | } |
17 | |
18 | macro_rules! impl_helper { |
19 | ($($t:ty)*) => ($(impl ReadNumberHelper for $t { |
20 | const ZERO: Self = 0; |
21 | #[inline] |
22 | fn checked_mul(&self, other: u32) -> Option<Self> { |
23 | Self::checked_mul(*self, other.try_into().ok()?) |
24 | } |
25 | #[inline] |
26 | fn checked_add(&self, other: u32) -> Option<Self> { |
27 | Self::checked_add(*self, other.try_into().ok()?) |
28 | } |
29 | })*) |
30 | } |
31 | |
32 | impl_helper! { u8 u16 u32 } |
33 | |
34 | struct Parser<'a> { |
35 | // Parsing as ASCII, so can use byte array. |
36 | state: &'a [u8], |
37 | } |
38 | |
39 | impl<'a> Parser<'a> { |
40 | fn new(input: &'a [u8]) -> Parser<'a> { |
41 | Parser { state: input } |
42 | } |
43 | |
44 | /// Run a parser, and restore the pre-parse state if it fails. |
45 | fn read_atomically<T, F>(&mut self, inner: F) -> Option<T> |
46 | where |
47 | F: FnOnce(&mut Parser<'_>) -> Option<T>, |
48 | { |
49 | let state = self.state; |
50 | let result = inner(self); |
51 | if result.is_none() { |
52 | self.state = state; |
53 | } |
54 | result |
55 | } |
56 | |
57 | /// Run a parser, but fail if the entire input wasn't consumed. |
58 | /// Doesn't run atomically. |
59 | fn parse_with<T, F>(&mut self, inner: F, kind: AddrKind) -> Result<T, AddrParseError> |
60 | where |
61 | F: FnOnce(&mut Parser<'_>) -> Option<T>, |
62 | { |
63 | let result = inner(self); |
64 | if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(kind)) |
65 | } |
66 | |
67 | /// Peek the next character from the input |
68 | fn peek_char(&self) -> Option<char> { |
69 | self.state.first().map(|&b| char::from(b)) |
70 | } |
71 | |
72 | /// Read the next character from the input |
73 | fn read_char(&mut self) -> Option<char> { |
74 | self.state.split_first().map(|(&b, tail)| { |
75 | self.state = tail; |
76 | char::from(b) |
77 | }) |
78 | } |
79 | |
80 | #[must_use ] |
81 | /// Read the next character from the input if it matches the target. |
82 | fn read_given_char(&mut self, target: char) -> Option<()> { |
83 | self.read_atomically(|p| { |
84 | p.read_char().and_then(|c| if c == target { Some(()) } else { None }) |
85 | }) |
86 | } |
87 | |
88 | /// Helper for reading separators in an indexed loop. Reads the separator |
89 | /// character iff index > 0, then runs the parser. When used in a loop, |
90 | /// the separator character will only be read on index > 0 (see |
91 | /// read_ipv4_addr for an example) |
92 | fn read_separator<T, F>(&mut self, sep: char, index: usize, inner: F) -> Option<T> |
93 | where |
94 | F: FnOnce(&mut Parser<'_>) -> Option<T>, |
95 | { |
96 | self.read_atomically(move |p| { |
97 | if index > 0 { |
98 | p.read_given_char(sep)?; |
99 | } |
100 | inner(p) |
101 | }) |
102 | } |
103 | |
104 | // Read a number off the front of the input in the given radix, stopping |
105 | // at the first non-digit character or eof. Fails if the number has more |
106 | // digits than max_digits or if there is no number. |
107 | fn read_number<T: ReadNumberHelper>( |
108 | &mut self, |
109 | radix: u32, |
110 | max_digits: Option<usize>, |
111 | allow_zero_prefix: bool, |
112 | ) -> Option<T> { |
113 | self.read_atomically(move |p| { |
114 | let mut result = T::ZERO; |
115 | let mut digit_count = 0; |
116 | let has_leading_zero = p.peek_char() == Some('0' ); |
117 | |
118 | while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { |
119 | result = result.checked_mul(radix)?; |
120 | result = result.checked_add(digit)?; |
121 | digit_count += 1; |
122 | if let Some(max_digits) = max_digits { |
123 | if digit_count > max_digits { |
124 | return None; |
125 | } |
126 | } |
127 | } |
128 | |
129 | if digit_count == 0 { |
130 | None |
131 | } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { |
132 | None |
133 | } else { |
134 | Some(result) |
135 | } |
136 | }) |
137 | } |
138 | |
139 | /// Read an IPv4 address. |
140 | fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> { |
141 | self.read_atomically(|p| { |
142 | let mut groups = [0; 4]; |
143 | |
144 | for (i, slot) in groups.iter_mut().enumerate() { |
145 | *slot = p.read_separator('.' , i, |p| { |
146 | // Disallow octal number in IP string. |
147 | // https://tools.ietf.org/html/rfc6943#section-3.1.1 |
148 | p.read_number(10, Some(3), false) |
149 | })?; |
150 | } |
151 | |
152 | Some(groups.into()) |
153 | }) |
154 | } |
155 | |
156 | /// Read an IPv6 Address. |
157 | fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> { |
158 | /// Read a chunk of an IPv6 address into `groups`. Returns the number |
159 | /// of groups read, along with a bool indicating if an embedded |
160 | /// trailing IPv4 address was read. Specifically, read a series of |
161 | /// colon-separated IPv6 groups (0x0000 - 0xFFFF), with an optional |
162 | /// trailing embedded IPv4 address. |
163 | fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) { |
164 | let limit = groups.len(); |
165 | |
166 | for (i, slot) in groups.iter_mut().enumerate() { |
167 | // Try to read a trailing embedded IPv4 address. There must be |
168 | // at least two groups left. |
169 | if i < limit - 1 { |
170 | let ipv4 = p.read_separator(':' , i, |p| p.read_ipv4_addr()); |
171 | |
172 | if let Some(v4_addr) = ipv4 { |
173 | let [one, two, three, four] = v4_addr.octets(); |
174 | groups[i + 0] = u16::from_be_bytes([one, two]); |
175 | groups[i + 1] = u16::from_be_bytes([three, four]); |
176 | return (i + 2, true); |
177 | } |
178 | } |
179 | |
180 | let group = p.read_separator(':' , i, |p| p.read_number(16, Some(4), true)); |
181 | |
182 | match group { |
183 | Some(g) => *slot = g, |
184 | None => return (i, false), |
185 | } |
186 | } |
187 | (groups.len(), false) |
188 | } |
189 | |
190 | self.read_atomically(|p| { |
191 | // Read the front part of the address; either the whole thing, or up |
192 | // to the first :: |
193 | let mut head = [0; 8]; |
194 | let (head_size, head_ipv4) = read_groups(p, &mut head); |
195 | |
196 | if head_size == 8 { |
197 | return Some(head.into()); |
198 | } |
199 | |
200 | // IPv4 part is not allowed before `::` |
201 | if head_ipv4 { |
202 | return None; |
203 | } |
204 | |
205 | // Read `::` if previous code parsed less than 8 groups. |
206 | // `::` indicates one or more groups of 16 bits of zeros. |
207 | p.read_given_char(':' )?; |
208 | p.read_given_char(':' )?; |
209 | |
210 | // Read the back part of the address. The :: must contain at least one |
211 | // set of zeroes, so our max length is 7. |
212 | let mut tail = [0; 7]; |
213 | let limit = 8 - (head_size + 1); |
214 | let (tail_size, _) = read_groups(p, &mut tail[..limit]); |
215 | |
216 | // Concat the head and tail of the IP address |
217 | head[(8 - tail_size)..8].copy_from_slice(&tail[..tail_size]); |
218 | |
219 | Some(head.into()) |
220 | }) |
221 | } |
222 | |
223 | /// Read an IP Address, either IPv4 or IPv6. |
224 | fn read_ip_addr(&mut self) -> Option<IpAddr> { |
225 | self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6)) |
226 | } |
227 | |
228 | /// Read a `:` followed by a port in base 10. |
229 | fn read_port(&mut self) -> Option<u16> { |
230 | self.read_atomically(|p| { |
231 | p.read_given_char(':' )?; |
232 | p.read_number(10, None, true) |
233 | }) |
234 | } |
235 | |
236 | /// Read a `%` followed by a scope ID in base 10. |
237 | fn read_scope_id(&mut self) -> Option<u32> { |
238 | self.read_atomically(|p| { |
239 | p.read_given_char('%' )?; |
240 | p.read_number(10, None, true) |
241 | }) |
242 | } |
243 | |
244 | /// Read an IPv4 address with a port. |
245 | fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> { |
246 | self.read_atomically(|p| { |
247 | let ip = p.read_ipv4_addr()?; |
248 | let port = p.read_port()?; |
249 | Some(SocketAddrV4::new(ip, port)) |
250 | }) |
251 | } |
252 | |
253 | /// Read an IPv6 address with a port. |
254 | fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> { |
255 | self.read_atomically(|p| { |
256 | p.read_given_char('[' )?; |
257 | let ip = p.read_ipv6_addr()?; |
258 | let scope_id = p.read_scope_id().unwrap_or(0); |
259 | p.read_given_char(']' )?; |
260 | |
261 | let port = p.read_port()?; |
262 | Some(SocketAddrV6::new(ip, port, 0, scope_id)) |
263 | }) |
264 | } |
265 | |
266 | /// Read an IP address with a port |
267 | fn read_socket_addr(&mut self) -> Option<SocketAddr> { |
268 | self.read_socket_addr_v4() |
269 | .map(SocketAddr::V4) |
270 | .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6)) |
271 | } |
272 | } |
273 | |
274 | impl IpAddr { |
275 | /// Parse an IP address from a slice of bytes. |
276 | /// |
277 | /// ``` |
278 | /// #![feature(addr_parse_ascii)] |
279 | /// |
280 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
281 | /// |
282 | /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); |
283 | /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); |
284 | /// |
285 | /// assert_eq!(IpAddr::parse_ascii(b"127.0.0.1" ), Ok(localhost_v4)); |
286 | /// assert_eq!(IpAddr::parse_ascii(b"::1" ), Ok(localhost_v6)); |
287 | /// ``` |
288 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
289 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
290 | Parser::new(b).parse_with(|p| p.read_ip_addr(), kind:AddrKind::Ip) |
291 | } |
292 | } |
293 | |
294 | #[stable (feature = "ip_addr" , since = "1.7.0" )] |
295 | impl FromStr for IpAddr { |
296 | type Err = AddrParseError; |
297 | fn from_str(s: &str) -> Result<IpAddr, AddrParseError> { |
298 | Self::parse_ascii(s.as_bytes()) |
299 | } |
300 | } |
301 | |
302 | impl Ipv4Addr { |
303 | /// Parse an IPv4 address from a slice of bytes. |
304 | /// |
305 | /// ``` |
306 | /// #![feature(addr_parse_ascii)] |
307 | /// |
308 | /// use std::net::Ipv4Addr; |
309 | /// |
310 | /// let localhost = Ipv4Addr::new(127, 0, 0, 1); |
311 | /// |
312 | /// assert_eq!(Ipv4Addr::parse_ascii(b"127.0.0.1" ), Ok(localhost)); |
313 | /// ``` |
314 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
315 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
316 | // don't try to parse if too long |
317 | if b.len() > 15 { |
318 | Err(AddrParseError(AddrKind::Ipv4)) |
319 | } else { |
320 | Parser::new(b).parse_with(|p| p.read_ipv4_addr(), kind:AddrKind::Ipv4) |
321 | } |
322 | } |
323 | } |
324 | |
325 | #[stable (feature = "rust1" , since = "1.0.0" )] |
326 | impl FromStr for Ipv4Addr { |
327 | type Err = AddrParseError; |
328 | fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> { |
329 | Self::parse_ascii(s.as_bytes()) |
330 | } |
331 | } |
332 | |
333 | impl Ipv6Addr { |
334 | /// Parse an IPv6 address from a slice of bytes. |
335 | /// |
336 | /// ``` |
337 | /// #![feature(addr_parse_ascii)] |
338 | /// |
339 | /// use std::net::Ipv6Addr; |
340 | /// |
341 | /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); |
342 | /// |
343 | /// assert_eq!(Ipv6Addr::parse_ascii(b"::1" ), Ok(localhost)); |
344 | /// ``` |
345 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
346 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
347 | Parser::new(b).parse_with(|p| p.read_ipv6_addr(), kind:AddrKind::Ipv6) |
348 | } |
349 | } |
350 | |
351 | #[stable (feature = "rust1" , since = "1.0.0" )] |
352 | impl FromStr for Ipv6Addr { |
353 | type Err = AddrParseError; |
354 | fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> { |
355 | Self::parse_ascii(s.as_bytes()) |
356 | } |
357 | } |
358 | |
359 | impl SocketAddrV4 { |
360 | /// Parse an IPv4 socket address from a slice of bytes. |
361 | /// |
362 | /// ``` |
363 | /// #![feature(addr_parse_ascii)] |
364 | /// |
365 | /// use std::net::{Ipv4Addr, SocketAddrV4}; |
366 | /// |
367 | /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); |
368 | /// |
369 | /// assert_eq!(SocketAddrV4::parse_ascii(b"127.0.0.1:8080" ), Ok(socket)); |
370 | /// ``` |
371 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
372 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
373 | Parser::new(b).parse_with(|p| p.read_socket_addr_v4(), kind:AddrKind::SocketV4) |
374 | } |
375 | } |
376 | |
377 | #[stable (feature = "socket_addr_from_str" , since = "1.5.0" )] |
378 | impl FromStr for SocketAddrV4 { |
379 | type Err = AddrParseError; |
380 | fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> { |
381 | Self::parse_ascii(s.as_bytes()) |
382 | } |
383 | } |
384 | |
385 | impl SocketAddrV6 { |
386 | /// Parse an IPv6 socket address from a slice of bytes. |
387 | /// |
388 | /// ``` |
389 | /// #![feature(addr_parse_ascii)] |
390 | /// |
391 | /// use std::net::{Ipv6Addr, SocketAddrV6}; |
392 | /// |
393 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); |
394 | /// |
395 | /// assert_eq!(SocketAddrV6::parse_ascii(b"[2001:db8::1]:8080" ), Ok(socket)); |
396 | /// ``` |
397 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
398 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
399 | Parser::new(b).parse_with(|p| p.read_socket_addr_v6(), kind:AddrKind::SocketV6) |
400 | } |
401 | } |
402 | |
403 | #[stable (feature = "socket_addr_from_str" , since = "1.5.0" )] |
404 | impl FromStr for SocketAddrV6 { |
405 | type Err = AddrParseError; |
406 | fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> { |
407 | Self::parse_ascii(s.as_bytes()) |
408 | } |
409 | } |
410 | |
411 | impl SocketAddr { |
412 | /// Parse a socket address from a slice of bytes. |
413 | /// |
414 | /// ``` |
415 | /// #![feature(addr_parse_ascii)] |
416 | /// |
417 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; |
418 | /// |
419 | /// let socket_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); |
420 | /// let socket_v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080); |
421 | /// |
422 | /// assert_eq!(SocketAddr::parse_ascii(b"127.0.0.1:8080" ), Ok(socket_v4)); |
423 | /// assert_eq!(SocketAddr::parse_ascii(b"[::1]:8080" ), Ok(socket_v6)); |
424 | /// ``` |
425 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
426 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
427 | Parser::new(b).parse_with(|p| p.read_socket_addr(), kind:AddrKind::Socket) |
428 | } |
429 | } |
430 | |
431 | #[stable (feature = "rust1" , since = "1.0.0" )] |
432 | impl FromStr for SocketAddr { |
433 | type Err = AddrParseError; |
434 | fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> { |
435 | Self::parse_ascii(s.as_bytes()) |
436 | } |
437 | } |
438 | |
439 | #[derive (Debug, Clone, PartialEq, Eq)] |
440 | enum AddrKind { |
441 | Ip, |
442 | Ipv4, |
443 | Ipv6, |
444 | Socket, |
445 | SocketV4, |
446 | SocketV6, |
447 | } |
448 | |
449 | /// An error which can be returned when parsing an IP address or a socket address. |
450 | /// |
451 | /// This error is used as the error type for the [`FromStr`] implementation for |
452 | /// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and |
453 | /// [`SocketAddrV6`]. |
454 | /// |
455 | /// # Potential causes |
456 | /// |
457 | /// `AddrParseError` may be thrown because the provided string does not parse as the given type, |
458 | /// often because it includes information only handled by a different address type. |
459 | /// |
460 | /// ```should_panic |
461 | /// use std::net::IpAddr; |
462 | /// let _foo: IpAddr = "127.0.0.1:8080" .parse().expect("Cannot handle the socket port" ); |
463 | /// ``` |
464 | /// |
465 | /// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead. |
466 | /// |
467 | /// ``` |
468 | /// use std::net::SocketAddr; |
469 | /// |
470 | /// // No problem, the `panic!` message has disappeared. |
471 | /// let _foo: SocketAddr = "127.0.0.1:8080" .parse().expect("unreachable panic" ); |
472 | /// ``` |
473 | #[stable (feature = "rust1" , since = "1.0.0" )] |
474 | #[derive (Debug, Clone, PartialEq, Eq)] |
475 | pub struct AddrParseError(AddrKind); |
476 | |
477 | #[stable (feature = "addr_parse_error_error" , since = "1.4.0" )] |
478 | impl fmt::Display for AddrParseError { |
479 | #[allow (deprecated, deprecated_in_future)] |
480 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
481 | fmt.write_str(self.description()) |
482 | } |
483 | } |
484 | |
485 | #[stable (feature = "addr_parse_error_error" , since = "1.4.0" )] |
486 | impl Error for AddrParseError { |
487 | #[allow (deprecated)] |
488 | fn description(&self) -> &str { |
489 | match self.0 { |
490 | AddrKind::Ip => "invalid IP address syntax" , |
491 | AddrKind::Ipv4 => "invalid IPv4 address syntax" , |
492 | AddrKind::Ipv6 => "invalid IPv6 address syntax" , |
493 | AddrKind::Socket => "invalid socket address syntax" , |
494 | AddrKind::SocketV4 => "invalid IPv4 socket address syntax" , |
495 | AddrKind::SocketV6 => "invalid IPv6 socket address syntax" , |
496 | } |
497 | } |
498 | } |
499 | |