Merge pull request #1027 from M3rs/refactor_uri
Refactor(uri): Remove usage of Url parse in Uri #1022
This commit is contained in:
		
							
								
								
									
										96
									
								
								src/uri.rs
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								src/uri.rs
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | |||||||
| use std::borrow::Cow; | use std::borrow::Cow; | ||||||
| use std::fmt::{Display, self}; | use std::fmt::{Display, self}; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
| use url::{self, Url}; | use url::Url; | ||||||
| use url::ParseError as UrlError; | use url::ParseError as UrlError; | ||||||
|  |  | ||||||
| use Error; | use Error; | ||||||
| @@ -54,43 +54,38 @@ impl Uri { | |||||||
|         } else if bytes == b"/" { |         } else if bytes == b"/" { | ||||||
|             Ok(Uri::default()) |             Ok(Uri::default()) | ||||||
|         } else if bytes.starts_with(b"/") { |         } else if bytes.starts_with(b"/") { | ||||||
|             let mut temp = "http://example.com".to_owned(); |  | ||||||
|             temp.push_str(s); |  | ||||||
|             let url = try!(Url::parse(&temp)); |  | ||||||
|             let query_len = url.query().unwrap_or("").len(); |  | ||||||
|             let fragment_len = url.fragment().unwrap_or("").len(); |  | ||||||
|             Ok(Uri { |             Ok(Uri { | ||||||
|                 source: s.to_owned().into(), |                 source: s.to_owned().into(), | ||||||
|                 scheme_end: None, |                 scheme_end: None, | ||||||
|                 authority_end: None, |                 authority_end: None, | ||||||
|                 query: if query_len > 0 { Some(query_len) } else { None }, |                 query: parse_query(s), | ||||||
|                 fragment: if fragment_len > 0 { Some(fragment_len) } else { None }, |                 fragment: parse_fragment(s), | ||||||
|             }) |             }) | ||||||
|         } else if s.contains("://") { |         } else if s.contains("://") { | ||||||
|             let url = try!(Url::parse(s)); |             let scheme = parse_scheme(s); | ||||||
|             let query_len = url.query().unwrap_or("").len(); |             let auth = parse_authority(s); | ||||||
|             let new_s = url.to_string(); |             if let Some(end) = scheme { | ||||||
|             let authority_end = { |                 match &s[..end] { | ||||||
|                 let v: Vec<&str> = new_s.split("://").collect(); |                     "ftp" | "gopher" | "http" | "https" | "ws" | "wss" => {}, | ||||||
|                 v.last().unwrap() |                     "blob" | "file" => return Err(Error::Method), | ||||||
|                         .split(url.path()) |                     _ => return Err(Error::Method), | ||||||
|                         .next() |                 } | ||||||
|                         .unwrap_or(&new_s) |                 match auth { | ||||||
|                         .len() + if v.len() == 2 { v[0].len() + 3 } else { 0 } |                     Some(a) => { | ||||||
|             }; |                         if (end + 3) == a { | ||||||
|             let fragment_len = url.fragment().unwrap_or("").len(); |                             return Err(Error::Method); | ||||||
|             match url.origin() { |                         } | ||||||
|                 url::Origin::Opaque(_) => Err(Error::Method), |                     }, | ||||||
|                 url::Origin::Tuple(scheme, _, _) => { |                     None => return Err(Error::Method), | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             Ok(Uri { |             Ok(Uri { | ||||||
|                         source: new_s.into(), |                 source: s.to_owned().into(), | ||||||
|                         scheme_end: Some(scheme.len()), |                 scheme_end: scheme, | ||||||
|                         authority_end: if authority_end > 0 { Some(authority_end) } else { None }, |                 authority_end: auth, | ||||||
|                         query: if query_len > 0 { Some(query_len) } else { None }, |                 query: parse_query(s), | ||||||
|                         fragment: if fragment_len > 0 { Some(fragment_len) } else { None }, |                 fragment: parse_fragment(s), | ||||||
|             }) |             }) | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |         } else { | ||||||
|             Ok(Uri { |             Ok(Uri { | ||||||
|                 source: s.to_owned().into(), |                 source: s.to_owned().into(), | ||||||
| @@ -110,6 +105,9 @@ impl Uri { | |||||||
|         let end = self.source.len() - if query_len > 0 { query_len + 1 } else { 0 } - |         let end = self.source.len() - if query_len > 0 { query_len + 1 } else { 0 } - | ||||||
|             if fragment_len > 0 { fragment_len + 1 } else { 0 }; |             if fragment_len > 0 { fragment_len + 1 } else { 0 }; | ||||||
|         if index >= end { |         if index >= end { | ||||||
|  |             if self.scheme().is_some() { | ||||||
|  |                 return "/" // absolute-form MUST have path | ||||||
|  |             } | ||||||
|             "" |             "" | ||||||
|         } else { |         } else { | ||||||
|             &self.source[index..end] |             &self.source[index..end] | ||||||
| @@ -129,6 +127,7 @@ impl Uri { | |||||||
|     pub fn authority(&self) -> Option<&str> { |     pub fn authority(&self) -> Option<&str> { | ||||||
|         if let Some(end) = self.authority_end { |         if let Some(end) = self.authority_end { | ||||||
|             let index = self.scheme_end.map(|i| i + 3).unwrap_or(0); |             let index = self.scheme_end.map(|i| i + 3).unwrap_or(0); | ||||||
|  |  | ||||||
|             Some(&self.source[index..end]) |             Some(&self.source[index..end]) | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
| @@ -179,6 +178,39 @@ impl Uri { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | fn parse_scheme(s: &str) -> Option<usize> { | ||||||
|  |     s.find(':') | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn parse_authority(s: &str) -> Option<usize> { | ||||||
|  |     let v: Vec<&str> = s.split("://").collect(); | ||||||
|  |     match v.last() { | ||||||
|  |         Some(auth) => Some(auth.split("/") | ||||||
|  |                            .next() | ||||||
|  |                            .unwrap_or(s) | ||||||
|  |                            .len() + if v.len() == 2 { v[0].len() + 3 } else { 0 }), | ||||||
|  |         None => None, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn parse_query(s: &str) -> Option<usize> { | ||||||
|  |     match s.find('?') { | ||||||
|  |         Some(i) => { | ||||||
|  |             let frag_pos = s.find('#').unwrap_or(s.len()); | ||||||
|  |  | ||||||
|  |             return Some(frag_pos - i - 1); | ||||||
|  |         }, | ||||||
|  |         None => None, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn parse_fragment(s: &str) -> Option<usize> { | ||||||
|  |     match s.find('#') { | ||||||
|  |         Some(i) => Some(s.len() - i - 1), | ||||||
|  |         None => None, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| impl FromStr for Uri { | impl FromStr for Uri { | ||||||
|     type Err = Error; |     type Err = Error; | ||||||
|  |  | ||||||
| @@ -305,7 +337,7 @@ test_parse! { | |||||||
|     "http://127.0.0.1:80", |     "http://127.0.0.1:80", | ||||||
|  |  | ||||||
|     scheme = Some("http"), |     scheme = Some("http"), | ||||||
|     authority = Some("127.0.0.1"), |     authority = Some("127.0.0.1:80"), | ||||||
|     path = "/", |     path = "/", | ||||||
|     query = None, |     query = None, | ||||||
|     fragment = None, |     fragment = None, | ||||||
| @@ -316,7 +348,7 @@ test_parse! { | |||||||
|     "https://127.0.0.1:443", |     "https://127.0.0.1:443", | ||||||
|  |  | ||||||
|     scheme = Some("https"), |     scheme = Some("https"), | ||||||
|     authority = Some("127.0.0.1"), |     authority = Some("127.0.0.1:443"), | ||||||
|     path = "/", |     path = "/", | ||||||
|     query = None, |     query = None, | ||||||
|     fragment = None, |     fragment = None, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user