parser.rs - source
Description: Source of the Rust file `library/core/src/net/parser.rs`.

#
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    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    501        match self.0 {
    502            AddrKind::Ip => "invalid IP address syntax",
    503            AddrKind::Ipv4 => "invalid IPv4 address syntax",
    504            AddrKind::Ipv6 => "invalid IPv6 address syntax",
    505            AddrKind::Socket => "invalid socket address syntax",
    506            AddrKind::SocketV4 => "invalid IPv4 socket address syntax",
    507            AddrKind::SocketV6 => "invalid IPv6 socket address syntax",
    508        }
    509        .fmt(f)
    510    }
    511}
    512
    513#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
    514impl Error for AddrParseError {}