Explorar o código

Add parse_path(). Fix #14.

Simon Sapin %!s(int64=12) %!d(string=hai) anos
pai
achega
03f6b332bc
Modificáronse 2 ficheiros con 58 adicións e 0 borrados
  1. 40 0
      src/lib.rs
  2. 18 0
      src/parser.rs

+ 40 - 0
src/lib.rs

@@ -349,6 +349,46 @@ impl<'a> UrlParser<'a> {
     pub fn parse(&self, input: &str) -> ParseResult<Url> {
         parser::parse_url(input, self)
     }
+
+    /// Parse `input` as a “standalone” URL path,
+    /// with an optional query string and fragment identifier.
+    ///
+    /// This is typically found in the start line of an HTTP header.
+    ///
+    /// Note that while the start line has no fragment identifier in the HTTP RFC,
+    /// servers typically parse it and ignore it
+    /// (rather than having it be part of the path or query string.)
+    ///
+    /// On success, return `(path, query_string, fragment_identifier)`
+    #[inline]
+    pub fn parse_path(&self, input: &str)
+                      -> ParseResult<(Vec<String>, Option<String>, Option<String>)> {
+        parser::parse_standalone_path(input, self)
+    }
+}
+
+
+/// Parse `input` as a “standalone” URL path,
+/// with an optional query string and fragment identifier.
+///
+/// This is typically found in the start line of an HTTP header.
+///
+/// Note that while the start line has no fragment identifier in the HTTP RFC,
+/// servers typically parse it and ignore it
+/// (rather than having it be part of the path or query string.)
+///
+/// On success, return `(path, query_string, fragment_identifier)`
+///
+/// ```rust
+/// let (path, query, fragment) = url::parse_path("/foo/bar/../baz?q=42").unwrap();
+/// assert_eq!(path, vec!["foo".to_string(), "baz".to_string()]);
+/// assert_eq!(query, Some("q=42".to_string()));
+/// assert_eq!(fragment, None);
+/// ```
+#[inline]
+pub fn parse_path(input: &str)
+                  -> ParseResult<(Vec<String>, Option<String>, Option<String>)> {
+    UrlParser::new().parse_path(input)
 }
 
 

+ 18 - 0
src/parser.rs

@@ -45,6 +45,7 @@ pub enum ParseError {
     InvalidPercentEncoded,
     InvalidAtSymbolInUser,
     ExpectedTwoSlashes,
+    ExpectedInitialSlash,
     NonUrlCodePoint,
     RelativeUrlWithScheme,
     RelativeUrlWithoutBase,
@@ -68,6 +69,7 @@ impl Show for ParseError {
             InvalidPercentEncoded => "Invalid percent-encoded sequence",
             InvalidAtSymbolInUser => "Invalid @-symbol in user",
             ExpectedTwoSlashes => "Expected two slashes (//)",
+            ExpectedInitialSlash => "Expected the input to start with a slash",
             NonUrlCodePoint => "Non URL code point",
             RelativeUrlWithScheme => "Relative URL with scheme",
             RelativeUrlWithoutBase => "Relative URL without a base",
@@ -472,6 +474,22 @@ fn parse_file_host<'a>(input: &'a str, parser: &UrlParser) -> ParseResult<(Host,
 }
 
 
+pub fn parse_standalone_path(input: &str, parser: &UrlParser)
+                             -> ParseResult<(Vec<String>, Option<String>, Option<String>)> {
+    if !input.starts_with("/") {
+        if input.starts_with("\\") {
+            try!(parser.parse_error(InvalidBackslash));
+        } else {
+            return Err(ExpectedInitialSlash)
+        }
+    }
+    let (path, remaining) = try!(parse_path(
+        [], input.slice_from(1), UrlParserContext, RelativeScheme(0), parser));
+    let (query, fragment) = try!(parse_query_and_fragment(remaining, parser));
+    Ok((path, query, fragment))
+}
+
+
 pub fn parse_path_start<'a>(input: &'a str, context: Context, scheme_type: SchemeType,
                             parser: &UrlParser)
                             -> ParseResult<(Vec<String>, &'a str)> {