Auto merge of #77626 - tamird:parse-scope-id, r=dtolnay
Parse SocketAddrV6::scope_id r? `@dtolnay`
This commit is contained in:
commit
c9ced8523b
|
@ -32,7 +32,7 @@ macro_rules! impl_helper {
|
||||||
})*)
|
})*)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_helper! { u8 u16 }
|
impl_helper! { u8 u16 u32 }
|
||||||
|
|
||||||
struct Parser<'a> {
|
struct Parser<'a> {
|
||||||
// parsing as ASCII, so can use byte array
|
// parsing as ASCII, so can use byte array
|
||||||
|
@ -75,9 +75,12 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the next character from the input if it matches the target
|
#[must_use]
|
||||||
fn read_given_char(&mut self, target: char) -> Option<char> {
|
/// Read the next character from the input if it matches the target.
|
||||||
self.read_atomically(|p| p.read_char().filter(|&c| c == target))
|
fn read_given_char(&mut self, target: char) -> Option<()> {
|
||||||
|
self.read_atomically(|p| {
|
||||||
|
p.read_char().and_then(|c| if c == target { Some(()) } else { None })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for reading separators in an indexed loop. Reads the separator
|
/// Helper for reading separators in an indexed loop. Reads the separator
|
||||||
|
@ -90,7 +93,7 @@ impl<'a> Parser<'a> {
|
||||||
{
|
{
|
||||||
self.read_atomically(move |p| {
|
self.read_atomically(move |p| {
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
let _ = p.read_given_char(sep)?;
|
p.read_given_char(sep)?;
|
||||||
}
|
}
|
||||||
inner(p)
|
inner(p)
|
||||||
})
|
})
|
||||||
|
@ -187,8 +190,8 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
// read `::` if previous code parsed less than 8 groups
|
// read `::` if previous code parsed less than 8 groups
|
||||||
// `::` indicates one or more groups of 16 bits of zeros
|
// `::` indicates one or more groups of 16 bits of zeros
|
||||||
let _ = p.read_given_char(':')?;
|
p.read_given_char(':')?;
|
||||||
let _ = p.read_given_char(':')?;
|
p.read_given_char(':')?;
|
||||||
|
|
||||||
// Read the back part of the address. The :: must contain at least one
|
// Read the back part of the address. The :: must contain at least one
|
||||||
// set of zeroes, so our max length is 7.
|
// set of zeroes, so our max length is 7.
|
||||||
|
@ -211,7 +214,15 @@ impl<'a> Parser<'a> {
|
||||||
/// Read a : followed by a port in base 10.
|
/// Read a : followed by a port in base 10.
|
||||||
fn read_port(&mut self) -> Option<u16> {
|
fn read_port(&mut self) -> Option<u16> {
|
||||||
self.read_atomically(|p| {
|
self.read_atomically(|p| {
|
||||||
let _ = p.read_given_char(':')?;
|
p.read_given_char(':')?;
|
||||||
|
p.read_number(10, None)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a % followed by a scope id in base 10.
|
||||||
|
fn read_scope_id(&mut self) -> Option<u32> {
|
||||||
|
self.read_atomically(|p| {
|
||||||
|
p.read_given_char('%')?;
|
||||||
p.read_number(10, None)
|
p.read_number(10, None)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -228,12 +239,13 @@ impl<'a> Parser<'a> {
|
||||||
/// Read an IPV6 address with a port
|
/// Read an IPV6 address with a port
|
||||||
fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
|
fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
|
||||||
self.read_atomically(|p| {
|
self.read_atomically(|p| {
|
||||||
let _ = p.read_given_char('[')?;
|
p.read_given_char('[')?;
|
||||||
let ip = p.read_ipv6_addr()?;
|
let ip = p.read_ipv6_addr()?;
|
||||||
let _ = p.read_given_char(']')?;
|
let scope_id = p.read_scope_id().unwrap_or(0);
|
||||||
|
p.read_given_char(']')?;
|
||||||
|
|
||||||
let port = p.read_port()?;
|
let port = p.read_port()?;
|
||||||
Some(SocketAddrV6::new(ip, port, 0, 0))
|
Some(SocketAddrV6::new(ip, port, 0, scope_id))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAdd
|
||||||
use crate::str::FromStr;
|
use crate::str::FromStr;
|
||||||
|
|
||||||
const PORT: u16 = 8080;
|
const PORT: u16 = 8080;
|
||||||
|
const SCOPE_ID: u32 = 1337;
|
||||||
|
|
||||||
const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1);
|
const IPV4: Ipv4Addr = Ipv4Addr::new(192, 168, 0, 1);
|
||||||
const IPV4_STR: &str = "192.168.0.1";
|
const IPV4_STR: &str = "192.168.0.1";
|
||||||
|
@ -13,6 +14,7 @@ const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1";
|
||||||
const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1";
|
const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1";
|
||||||
const IPV6_STR_V4: &str = "2001:db8::192.168.0.1";
|
const IPV6_STR_V4: &str = "2001:db8::192.168.0.1";
|
||||||
const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080";
|
const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080";
|
||||||
|
const IPV6_STR_PORT_SCOPE_ID: &str = "[2001:db8::c0a8:1%1337]:8080";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_ipv4() {
|
fn parse_ipv4() {
|
||||||
|
@ -74,8 +76,8 @@ fn parse_socket_v4() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_socket_v6() {
|
fn parse_socket_v6() {
|
||||||
let result: SocketAddrV6 = IPV6_STR_PORT.parse().unwrap();
|
assert_eq!(IPV6_STR_PORT.parse(), Ok(SocketAddrV6::new(IPV6, PORT, 0, 0)));
|
||||||
assert_eq!(result, SocketAddrV6::new(IPV6, PORT, 0, 0));
|
assert_eq!(IPV6_STR_PORT_SCOPE_ID.parse(), Ok(SocketAddrV6::new(IPV6, PORT, 0, SCOPE_ID)));
|
||||||
|
|
||||||
assert!(SocketAddrV6::from_str(IPV4_STR).is_err());
|
assert!(SocketAddrV6::from_str(IPV4_STR).is_err());
|
||||||
assert!(SocketAddrV6::from_str(IPV4_STR_PORT).is_err());
|
assert!(SocketAddrV6::from_str(IPV4_STR_PORT).is_err());
|
||||||
|
|
Loading…
Reference in New Issue