core/net/
parser.rs

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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy