diff options
Diffstat (limited to 'src/parse_host_port.rs')
-rw-r--r-- | src/parse_host_port.rs | 117 |
1 files changed, 67 insertions, 50 deletions
diff --git a/src/parse_host_port.rs b/src/parse_host_port.rs index abb34e1..c5cdcc6 100644 --- a/src/parse_host_port.rs +++ b/src/parse_host_port.rs @@ -1,14 +1,16 @@ use std::convert::TryFrom; -use super::character_classes::{ - HEXDIG, - IPV_FUTURE_LAST_PART, - REG_NAME_NOT_PCT_ENCODED, +use super::{ + character_classes::{ + HEXDIG, + IPV_FUTURE_LAST_PART, + REG_NAME_NOT_PCT_ENCODED, + }, + context::Context, + error::Error, + percent_encoded_character_decoder::PercentEncodedCharacterDecoder, + validate_ipv6_address::validate_ipv6_address, }; -use super::context::Context; -use super::error::Error; -use super::percent_encoded_character_decoder::PercentEncodedCharacterDecoder; -use super::validate_ipv6_address::validate_ipv6_address; struct Shared { host: Vec<u8>, @@ -28,7 +30,7 @@ enum State { Port(Shared), } -impl State{ +impl State { fn finalize(self) -> Result<(Vec<u8>, Option<u16>), Error> { match self { Self::PercentEncodedCharacter(_) @@ -49,12 +51,10 @@ impl State{ None } else { match state.port_string.parse::<u16>() { - Ok(port) => { - Some(port) - }, + Ok(port) => Some(port), Err(error) => { return Err(Error::IllegalPortNumber(error)); - } + }, } }; Ok((state.host, port)) @@ -63,7 +63,7 @@ impl State{ } fn new(host_port_string: &str) -> (Self, &str) { - let mut shared = Shared{ + let mut shared = Shared { host: Vec::<u8>::new(), host_is_reg_name: false, ipv6_address: String::new(), @@ -74,38 +74,39 @@ impl State{ if host_port_string.starts_with("[v") { host_port_string = &host_port_string[2..]; shared.host.push(b'v'); - ( - Self::IpvFutureNumber(shared), - host_port_string - ) + (Self::IpvFutureNumber(shared), host_port_string) } else if host_port_string.starts_with('[') { host_port_string = &host_port_string[1..]; - ( - Self::Ipv6Address(shared), - host_port_string - ) + (Self::Ipv6Address(shared), host_port_string) } else { shared.host_is_reg_name = true; - ( - Self::NotIpLiteral(shared), - host_port_string - ) + (Self::NotIpLiteral(shared), host_port_string) } } - fn next(self, c: char) -> Result<Self, Error> { + fn next( + self, + c: char, + ) -> Result<Self, Error> { match self { Self::NotIpLiteral(state) => Self::next_not_ip_literal(state, c), - Self::PercentEncodedCharacter(state) => Self::next_percent_encoded_character(state, c), + Self::PercentEncodedCharacter(state) => { + Self::next_percent_encoded_character(state, c) + }, Self::Ipv6Address(state) => Self::next_ipv6_address(state, c), - Self::IpvFutureNumber(state) => Self::next_ipv_future_number(state, c), + Self::IpvFutureNumber(state) => { + Self::next_ipv_future_number(state, c) + }, Self::IpvFutureBody(state) => Self::next_ipv_future_body(state, c), Self::GarbageCheck(state) => Self::next_garbage_check(state, c), Self::Port(state) => Self::next_port(state, c), } } - fn next_not_ip_literal(state: Shared, c: char) -> Result<Self, Error> { + fn next_not_ip_literal( + state: Shared, + c: char, + ) -> Result<Self, Error> { let mut state = state; if c == '%' { Ok(Self::PercentEncodedCharacter(state)) @@ -119,7 +120,10 @@ impl State{ } } - fn next_percent_encoded_character(state: Shared, c: char) -> Result<Self, Error> { + fn next_percent_encoded_character( + state: Shared, + c: char, + ) -> Result<Self, Error> { let mut state = state; // We can't use `Option::map_or` (or `Option::map_or_else`, for similar // reasons) in this case because the closure would take ownership of @@ -134,13 +138,18 @@ impl State{ } } - fn next_ipv6_address(state: Shared, c: char) -> Result<Self, Error> { + fn next_ipv6_address( + state: Shared, + c: char, + ) -> Result<Self, Error> { let mut state = state; if c == ']' { validate_ipv6_address(&state.ipv6_address)?; - state.host = state.ipv6_address.chars().map( - |c| u8::try_from(c as u32).unwrap() - ).collect(); + state.host = state + .ipv6_address + .chars() + .map(|c| u8::try_from(c as u32).unwrap()) + .collect(); Ok(Self::GarbageCheck(state)) } else { state.ipv6_address.push(c); @@ -148,7 +157,10 @@ impl State{ } } - fn next_ipv_future_number(state: Shared, c: char) -> Result<Self, Error> { + fn next_ipv_future_number( + state: Shared, + c: char, + ) -> Result<Self, Error> { let mut state = state; if c == '.' { state.host.push(b'.'); @@ -163,7 +175,10 @@ impl State{ } } - fn next_ipv_future_body(state: Shared, c: char) -> Result<Self, Error> { + fn next_ipv_future_body( + state: Shared, + c: char, + ) -> Result<Self, Error> { let mut state = state; if c == ']' { Ok(Self::GarbageCheck(state)) @@ -175,7 +190,10 @@ impl State{ } } - fn next_garbage_check(state: Shared, c: char) -> Result<Self, Error> { + fn next_garbage_check( + state: Shared, + c: char, + ) -> Result<Self, Error> { // illegal to have anything else, unless it's a colon, // in which case it's a port delimiter if c == ':' { @@ -185,22 +203,26 @@ impl State{ } } - fn next_port(state: Shared, c: char) -> Result<Self, Error> { + fn next_port( + state: Shared, + c: char, + ) -> Result<Self, Error> { let mut state = state; state.port_string.push(c); Ok(Self::Port(state)) } } -pub fn parse_host_port<T>(host_port_string: T) -> Result<(Vec<u8>, Option<u16>), Error> - where T: AsRef<str> +pub fn parse_host_port<T>( + host_port_string: T +) -> Result<(Vec<u8>, Option<u16>), Error> +where + T: AsRef<str>, { let (machine, host_port_string) = State::new(host_port_string.as_ref()); host_port_string .chars() - .try_fold(machine, |machine, c| { - machine.next(c) - })? + .try_fold(machine, |machine, c| machine.next(c))? .finalize() } @@ -270,11 +292,7 @@ mod tests { #[test] fn truncated_host() { - let test_vectors = [ - "[::ffff:1.2.3.4/", - "[:]/", - "[v]/", - ]; + let test_vectors = ["[::ffff:1.2.3.4/", "[:]/", "[v]/"]; for test_vector in &test_vectors { assert_eq!( Err(Error::TruncatedHost), @@ -292,5 +310,4 @@ mod tests { Err(Error::IllegalPortNumber(_)) )); } - } |