From 9082d329da57d96a55f519454d1b82b9c3e7f72e Mon Sep 17 00:00:00 2001 From: Richard Walters Date: Mon, 12 Oct 2020 15:31:25 -0700 Subject: Make functions accepting references more generic using AsRef --- src/lib.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 554a4a2..54c31e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -263,7 +263,9 @@ fn encode_element( } -fn validate_ipv4_address(address: &str) -> Result<(), Error> { +fn validate_ipv4_address(address: T) -> Result<(), Error> + where T: AsRef +{ #[derive(PartialEq)] enum State { NotInOctet, @@ -276,7 +278,7 @@ fn validate_ipv4_address(address: &str) -> Result<(), Error> { // // Validation of the octet_buffer is done in two places; consider // how to remove the redundant code. - for c in address.chars() { + for c in address.as_ref().chars() { state = match state { State::NotInOctet if DIGIT.contains(&c) => { octet_buffer.push(c); @@ -328,7 +330,9 @@ fn validate_ipv4_address(address: &str) -> Result<(), Error> { // TODO: Clippy correctly advises us that this function needs refactoring // because it has too many lines. We'll get back to that. #[allow(clippy::too_many_lines)] -fn validate_ipv6_address(address: &str) -> Result<(), Error> { +fn validate_ipv6_address(address: T) -> Result<(), Error> + where T: AsRef +{ #[derive(PartialEq)] enum ValidationState { NoGroupsYet, @@ -344,6 +348,7 @@ fn validate_ipv6_address(address: &str) -> Result<(), Error> { let mut double_colon_encountered = false; let mut potential_ipv4_address_start = 0; let mut ipv4_address_encountered = false; + let address = address.as_ref(); for (i, c) in address.char_indices() { state = match state { ValidationState::NoGroupsYet => { @@ -577,7 +582,10 @@ impl Uri { !Self::is_path_absolute(&self.path) } - fn can_navigate_path_up_one_level(path: &[Vec]) -> bool { + fn can_navigate_path_up_one_level(path: T) -> bool + where T: AsRef<[Vec]> + { + let path = path.as_ref(); match path.first() { // First segment empty means path has leading slash, // so we can only navigate up if there are two or more segments. @@ -624,10 +632,12 @@ impl Uri { .collect() } - fn decode_query_or_fragment( - query_or_fragment: &str, + fn decode_query_or_fragment( + query_or_fragment: T, context: Context, - ) -> Result, Error> { + ) -> Result, Error> + where T: AsRef + { Self::decode_element( query_or_fragment, &QUERY_OR_FRAGMENT_NOT_PCT_ENCODED, @@ -647,8 +657,10 @@ impl Uri { .map(Authority::host) } - fn is_path_absolute(path: &[Vec]) -> bool { - match path { + fn is_path_absolute(path: T) -> bool + where T: AsRef<[Vec]> + { + match path.as_ref() { [segment, ..] if segment.is_empty() => true, _ => false } @@ -667,7 +679,9 @@ impl Uri { // in RFC 3986 (https://tools.ietf.org/html/rfc3986) to the path // segments of the URI, in order to normalize the path // (apply and remove "." and ".." segments). - fn normalize_path(original_path: &[Vec]) -> Vec> { + fn normalize_path(original_path: T) -> Vec> + where T: AsRef<[Vec]> + { // Rebuild the path one segment // at a time, removing and applying special // navigation segments ("." and "..") as we go. @@ -679,7 +693,7 @@ impl Uri { // empty segments. Conclusion: We should refactor this. let mut at_directory_level = false; let mut normalized_path = Vec::new(); - for segment in original_path { + for segment in original_path.as_ref() { if segment == b"." { at_directory_level = true; } else if segment == b".." { @@ -716,8 +730,10 @@ impl Uri { normalized_path } - pub fn parse(uri_string: &str) -> Result { - let (scheme, rest) = Self::parse_scheme(uri_string)?; + pub fn parse(uri_string: T) -> Result + where T: AsRef + { + let (scheme, rest) = Self::parse_scheme(uri_string.as_ref())?; let path_end = rest .find(&['?', '#'][..]) .unwrap_or_else(|| rest.len()); @@ -737,7 +753,9 @@ impl Uri { // TODO: Needs refactoring, as Clippy dutifully told us. #[allow(clippy::too_many_lines)] - fn parse_authority(authority_string: &str) -> Result { + fn parse_authority(authority_string: T) -> Result + where T: AsRef + { // These are the various states for the state machine implemented // below to correctly split up and validate the URI substring // containing the host and potentially a port number as well. @@ -753,6 +771,7 @@ impl Uri { }; // First, check if there is a UserInfo, and if so, extract it. + let authority_string = authority_string.as_ref(); let (userinfo, mut host_port_string) = match authority_string.find('@') { Some(user_info_delimiter) => ( Some( @@ -915,8 +934,10 @@ impl Uri { } } - fn parse_path(path_string: &str) -> Result>, Error> { - match path_string { + fn parse_path(path_string: T) -> Result>, Error> + where T: AsRef + { + match path_string.as_ref() { "/" => { // Special case of an empty absolute path, which we want to // represent as single empty-string element to indicate that it @@ -945,7 +966,10 @@ impl Uri { } } - fn parse_query(query_and_or_fragment: &str) -> Result>, Error> { + fn parse_query(query_and_or_fragment: T) -> Result>, Error> + where T: AsRef + { + let query_and_or_fragment = query_and_or_fragment.as_ref(); if query_and_or_fragment.is_empty() { Ok(None) } else { @@ -1106,7 +1130,10 @@ impl Uri { self.path = path.map(std::borrow::ToOwned::to_owned).collect(); } - pub fn set_path_from_str<'a>(&mut self, path: &'a str) { + pub fn set_path_from_str<'a, T>(&mut self, path: T) + where T: AsRef + 'a + { + let path = path.as_ref(); if path.is_empty() { self.set_path(std::iter::empty()); } else { @@ -1131,10 +1158,13 @@ impl Uri { Ok(()) } - fn split_authority_from_path_and_parse_them( - authority_and_path_string: &str - ) -> Result<(Option, Vec>), Error> { + fn split_authority_from_path_and_parse_them( + authority_and_path_string: T + ) -> Result<(Option, Vec>), Error> + where T: AsRef + { // Split authority from path. If there is an authority, parse it. + let authority_and_path_string = authority_and_path_string.as_ref(); if authority_and_path_string.starts_with("//") { // Strip off authority marker. let authority_and_path_string = &authority_and_path_string[2..]; -- cgit v1.2.3