]> git.proxmox.com Git - rustc.git/blame - library/std/src/net/parser.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / library / std / src / net / parser.rs
CommitLineData
85aaf69f
SL
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
1b1a35ee
XL
6#[cfg(test)]
7mod tests;
8
29967ef6 9use crate::convert::TryInto as _;
532ac7d7
XL
10use crate::error::Error;
11use crate::fmt;
12use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
13use crate::str::FromStr;
85aaf69f 14
29967ef6
XL
15trait ReadNumberHelper: crate::marker::Sized {
16 const ZERO: Self;
17 fn checked_mul(&self, other: u32) -> Option<Self>;
18 fn checked_add(&self, other: u32) -> Option<Self>;
19}
20
21macro_rules! impl_helper {
22 ($($t:ty)*) => ($(impl ReadNumberHelper for $t {
23 const ZERO: Self = 0;
24 #[inline]
25 fn checked_mul(&self, other: u32) -> Option<Self> {
26 Self::checked_mul(*self, other.try_into().ok()?)
27 }
28 #[inline]
29 fn checked_add(&self, other: u32) -> Option<Self> {
30 Self::checked_add(*self, other.try_into().ok()?)
31 }
32 })*)
33}
34
35impl_helper! { u8 u16 u32 }
36
85aaf69f 37struct Parser<'a> {
6a06907d 38 // Parsing as ASCII, so can use byte array.
f035d41b 39 state: &'a [u8],
85aaf69f
SL
40}
41
42impl<'a> Parser<'a> {
f035d41b
XL
43 fn new(input: &'a str) -> Parser<'a> {
44 Parser { state: input.as_bytes() }
85aaf69f
SL
45 }
46
6a06907d 47 /// Run a parser, and restore the pre-parse state if it fails.
f035d41b 48 fn read_atomically<T, F>(&mut self, inner: F) -> Option<T>
60c5eb7d 49 where
532ac7d7 50 F: FnOnce(&mut Parser<'_>) -> Option<T>,
85aaf69f 51 {
f035d41b
XL
52 let state = self.state;
53 let result = inner(self);
54 if result.is_none() {
55 self.state = state;
85aaf69f 56 }
f035d41b 57 result
85aaf69f
SL
58 }
59
f035d41b
XL
60 /// Run a parser, but fail if the entire input wasn't consumed.
61 /// Doesn't run atomically.
f035d41b 62 fn parse_with<T, F>(&mut self, inner: F) -> Result<T, AddrParseError>
60c5eb7d 63 where
f035d41b 64 F: FnOnce(&mut Parser<'_>) -> Option<T>,
85aaf69f 65 {
29967ef6
XL
66 let result = inner(self);
67 if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(()))
85aaf69f
SL
68 }
69
f035d41b 70 /// Read the next character from the input
85aaf69f 71 fn read_char(&mut self) -> Option<char> {
f035d41b
XL
72 self.state.split_first().map(|(&b, tail)| {
73 self.state = tail;
29967ef6 74 char::from(b)
85aaf69f
SL
75 })
76 }
77
29967ef6
XL
78 #[must_use]
79 /// Read the next character from the input if it matches the target.
80 fn read_given_char(&mut self, target: char) -> Option<()> {
81 self.read_atomically(|p| {
82 p.read_char().and_then(|c| if c == target { Some(()) } else { None })
83 })
85aaf69f
SL
84 }
85
f035d41b
XL
86 /// Helper for reading separators in an indexed loop. Reads the separator
87 /// character iff index > 0, then runs the parser. When used in a loop,
88 /// the separator character will only be read on index > 0 (see
89 /// read_ipv4_addr for an example)
90 fn read_separator<T, F>(&mut self, sep: char, index: usize, inner: F) -> Option<T>
91 where
92 F: FnOnce(&mut Parser<'_>) -> Option<T>,
93 {
94 self.read_atomically(move |p| {
95 if index > 0 {
29967ef6 96 p.read_given_char(sep)?;
f035d41b
XL
97 }
98 inner(p)
99 })
85aaf69f
SL
100 }
101
f035d41b
XL
102 // Read a number off the front of the input in the given radix, stopping
103 // at the first non-digit character or eof. Fails if the number has more
29967ef6
XL
104 // digits than max_digits or if there is no number.
105 fn read_number<T: ReadNumberHelper>(
106 &mut self,
107 radix: u32,
108 max_digits: Option<usize>,
109 ) -> Option<T> {
f035d41b 110 self.read_atomically(move |p| {
29967ef6 111 let mut result = T::ZERO;
f035d41b
XL
112 let mut digit_count = 0;
113
29967ef6
XL
114 while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
115 result = result.checked_mul(radix)?;
116 result = result.checked_add(digit)?;
f035d41b 117 digit_count += 1;
29967ef6
XL
118 if let Some(max_digits) = max_digits {
119 if digit_count > max_digits {
120 return None;
121 }
f035d41b 122 }
85aaf69f
SL
123 }
124
f035d41b
XL
125 if digit_count == 0 { None } else { Some(result) }
126 })
85aaf69f
SL
127 }
128
6a06907d 129 /// Read an IPv4 address.
85aaf69f 130 fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
f035d41b
XL
131 self.read_atomically(|p| {
132 let mut groups = [0; 4];
85aaf69f 133
f035d41b 134 for (i, slot) in groups.iter_mut().enumerate() {
29967ef6 135 *slot = p.read_separator('.', i, |p| p.read_number(10, None))?;
f035d41b
XL
136 }
137
138 Some(groups.into())
139 })
140 }
85aaf69f 141
6a06907d 142 /// Read an IPv6 Address.
f035d41b 143 fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
6a06907d 144 /// Read a chunk of an IPv6 address into `groups`. Returns the number
f035d41b 145 /// of groups read, along with a bool indicating if an embedded
6a06907d
XL
146 /// trailing IPv4 address was read. Specifically, read a series of
147 /// colon-separated IPv6 groups (0x0000 - 0xFFFF), with an optional
148 /// trailing embedded IPv4 address.
f035d41b
XL
149 fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) {
150 let limit = groups.len();
151
152 for (i, slot) in groups.iter_mut().enumerate() {
6a06907d 153 // Try to read a trailing embedded IPv4 address. There must be
f035d41b 154 // at least two groups left.
85aaf69f 155 if i < limit - 1 {
f035d41b
XL
156 let ipv4 = p.read_separator(':', i, |p| p.read_ipv4_addr());
157
85aaf69f 158 if let Some(v4_addr) = ipv4 {
29967ef6
XL
159 let [one, two, three, four] = v4_addr.octets();
160 groups[i + 0] = u16::from_be_bytes([one, two]);
161 groups[i + 1] = u16::from_be_bytes([three, four]);
85aaf69f
SL
162 return (i + 2, true);
163 }
164 }
165
29967ef6 166 let group = p.read_separator(':', i, |p| p.read_number(16, Some(4)));
f035d41b 167
85aaf69f 168 match group {
29967ef6 169 Some(g) => *slot = g,
60c5eb7d 170 None => return (i, false),
85aaf69f 171 }
85aaf69f 172 }
f035d41b 173 (groups.len(), false)
85aaf69f
SL
174 }
175
f035d41b
XL
176 self.read_atomically(|p| {
177 // Read the front part of the address; either the whole thing, or up
178 // to the first ::
179 let mut head = [0; 8];
180 let (head_size, head_ipv4) = read_groups(p, &mut head);
85aaf69f 181
f035d41b
XL
182 if head_size == 8 {
183 return Some(head.into());
184 }
85aaf69f 185
f035d41b
XL
186 // IPv4 part is not allowed before `::`
187 if head_ipv4 {
188 return None;
189 }
85aaf69f 190
6a06907d
XL
191 // Read `::` if previous code parsed less than 8 groups.
192 // `::` indicates one or more groups of 16 bits of zeros.
29967ef6
XL
193 p.read_given_char(':')?;
194 p.read_given_char(':')?;
85aaf69f 195
f035d41b
XL
196 // Read the back part of the address. The :: must contain at least one
197 // set of zeroes, so our max length is 7.
198 let mut tail = [0; 7];
199 let limit = 8 - (head_size + 1);
200 let (tail_size, _) = read_groups(p, &mut tail[..limit]);
85aaf69f 201
f035d41b
XL
202 // Concat the head and tail of the IP address
203 head[(8 - tail_size)..8].copy_from_slice(&tail[..tail_size]);
204
205 Some(head.into())
206 })
85aaf69f
SL
207 }
208
6a06907d 209 /// Read an IP Address, either IPv4 or IPv6.
85aaf69f 210 fn read_ip_addr(&mut self) -> Option<IpAddr> {
f035d41b 211 self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6))
85aaf69f
SL
212 }
213
6a06907d 214 /// Read a `:` followed by a port in base 10.
f035d41b
XL
215 fn read_port(&mut self) -> Option<u16> {
216 self.read_atomically(|p| {
29967ef6
XL
217 p.read_given_char(':')?;
218 p.read_number(10, None)
219 })
220 }
221
6a06907d 222 /// Read a `%` followed by a scope ID in base 10.
29967ef6
XL
223 fn read_scope_id(&mut self) -> Option<u32> {
224 self.read_atomically(|p| {
225 p.read_given_char('%')?;
226 p.read_number(10, None)
f035d41b
XL
227 })
228 }
b039eaaf 229
6a06907d 230 /// Read an IPv4 address with a port.
f035d41b
XL
231 fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
232 self.read_atomically(|p| {
233 let ip = p.read_ipv4_addr()?;
234 let port = p.read_port()?;
235 Some(SocketAddrV4::new(ip, port))
b039eaaf
SL
236 })
237 }
238
6a06907d 239 /// Read an IPv6 address with a port.
b039eaaf 240 fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
f035d41b 241 self.read_atomically(|p| {
29967ef6 242 p.read_given_char('[')?;
f035d41b 243 let ip = p.read_ipv6_addr()?;
29967ef6
XL
244 let scope_id = p.read_scope_id().unwrap_or(0);
245 p.read_given_char(']')?;
f035d41b
XL
246
247 let port = p.read_port()?;
29967ef6 248 Some(SocketAddrV6::new(ip, port, 0, scope_id))
c34b1796 249 })
85aaf69f 250 }
b039eaaf 251
f035d41b 252 /// Read an IP address with a port
b039eaaf 253 fn read_socket_addr(&mut self) -> Option<SocketAddr> {
dfeec247
XL
254 self.read_socket_addr_v4()
255 .map(SocketAddr::V4)
60c5eb7d 256 .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6))
b039eaaf 257 }
85aaf69f
SL
258}
259
c30ab7b3 260#[stable(feature = "ip_addr", since = "1.7.0")]
85aaf69f 261impl FromStr for IpAddr {
c34b1796
AL
262 type Err = AddrParseError;
263 fn from_str(s: &str) -> Result<IpAddr, AddrParseError> {
f035d41b 264 Parser::new(s).parse_with(|p| p.read_ip_addr())
85aaf69f
SL
265 }
266}
267
c34b1796 268#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 269impl FromStr for Ipv4Addr {
c34b1796
AL
270 type Err = AddrParseError;
271 fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
f035d41b 272 Parser::new(s).parse_with(|p| p.read_ipv4_addr())
85aaf69f
SL
273 }
274}
275
c34b1796 276#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 277impl FromStr for Ipv6Addr {
c34b1796
AL
278 type Err = AddrParseError;
279 fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
f035d41b 280 Parser::new(s).parse_with(|p| p.read_ipv6_addr())
85aaf69f
SL
281 }
282}
283
b039eaaf
SL
284#[stable(feature = "socket_addr_from_str", since = "1.5.0")]
285impl FromStr for SocketAddrV4 {
286 type Err = AddrParseError;
287 fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
f035d41b 288 Parser::new(s).parse_with(|p| p.read_socket_addr_v4())
b039eaaf
SL
289 }
290}
291
292#[stable(feature = "socket_addr_from_str", since = "1.5.0")]
293impl FromStr for SocketAddrV6 {
294 type Err = AddrParseError;
295 fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
f035d41b 296 Parser::new(s).parse_with(|p| p.read_socket_addr_v6())
b039eaaf
SL
297 }
298}
299
c34b1796 300#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 301impl FromStr for SocketAddr {
c34b1796
AL
302 type Err = AddrParseError;
303 fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
f035d41b 304 Parser::new(s).parse_with(|p| p.read_socket_addr())
85aaf69f
SL
305 }
306}
307
cc61c64b
XL
308/// An error which can be returned when parsing an IP address or a socket address.
309///
310/// This error is used as the error type for the [`FromStr`] implementation for
311/// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and
312/// [`SocketAddrV6`].
313///
0531ce1d
XL
314/// # Potential causes
315///
316/// `AddrParseError` may be thrown because the provided string does not parse as the given type,
317/// often because it includes information only handled by a different address type.
318///
319/// ```should_panic
320/// use std::net::IpAddr;
321/// let _foo: IpAddr = "127.0.0.1:8080".parse().expect("Cannot handle the socket port");
322/// ```
323///
324/// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead.
325///
326/// ```
327/// use std::net::SocketAddr;
328///
329/// // No problem, the `panic!` message has disappeared.
330/// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic");
331/// ```
c34b1796 332#[stable(feature = "rust1", since = "1.0.0")]
9e0c209e 333#[derive(Debug, Clone, PartialEq, Eq)]
c34b1796 334pub struct AddrParseError(());
e9174d1e
SL
335
336#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
337impl fmt::Display for AddrParseError {
dfeec247 338 #[allow(deprecated, deprecated_in_future)]
532ac7d7 339 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
e9174d1e
SL
340 fmt.write_str(self.description())
341 }
342}
343
344#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
345impl Error for AddrParseError {
dfeec247 346 #[allow(deprecated)]
e9174d1e
SL
347 fn description(&self) -> &str {
348 "invalid IP address syntax"
349 }
350}