Ver Fonte

Refactor some repeating/redundant code.

Simon Sapin há 12 anos atrás
pai
commit
da7f23905b
4 ficheiros alterados com 72 adições e 63 exclusões
  1. 6 5
      make_encode_sets.py
  2. 36 0
      src/encode_sets.rs
  3. 23 57
      src/parser.rs
  4. 7 1
      src/url.rs

+ 6 - 5
make_encode_sets.py

@@ -22,11 +22,12 @@ print('''\
 // Generated by make_encode_sets.py
 ''')
 for name, encoded in [
-    ('SIMPLE_ENCODE_SET', ''),
-    ('DEFAULT_ENCODE_SET', ' "#<>?`'),
-    ('USERINFO_ENCODE_SET', ' "#<>?`@'),
-    ('PASSWORD_ENCODE_SET', ' "#<>?`@/\\'),
-    ('USERNAME_ENCODE_SET', ' "#<>?`@/\\:'),
+    ('SIMPLE_ENCODE_SET',   ''),
+    ('QUERY_ENCODE_SET',    ' "#<>`'),
+    ('DEFAULT_ENCODE_SET',  ' "#<>`?'),
+    ('USERINFO_ENCODE_SET', ' "#<>`?@'),
+    ('PASSWORD_ENCODE_SET', ' "#<>`?@/\\'),
+    ('USERNAME_ENCODE_SET', ' "#<>`?@/\\:'),
 ]:
     print(
         "pub static %s: [&'static str, ..256] = [\n%s\n];\n\n"

+ 36 - 0
src/encode_sets.rs

@@ -44,6 +44,42 @@ pub static SIMPLE_ENCODE_SET: [&'static str, ..256] = [
 ];
 
 
+pub static QUERY_ENCODE_SET: [&'static str, ..256] = [
+   "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
+   "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F",
+   "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+   "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F",
+   "%20", "!", "%22", "%23", "$", "%", "&", "'",
+   "(", ")", "*", "+", ",", "-", ".", "/",
+   "0", "1", "2", "3", "4", "5", "6", "7",
+   "8", "9", ":", ";", "%3C", "=", "%3E", "?",
+   "@", "A", "B", "C", "D", "E", "F", "G",
+   "H", "I", "J", "K", "L", "M", "N", "O",
+   "P", "Q", "R", "S", "T", "U", "V", "W",
+   "X", "Y", "Z", "[", "\\", "]", "^", "_",
+   "%60", "a", "b", "c", "d", "e", "f", "g",
+   "h", "i", "j", "k", "l", "m", "n", "o",
+   "p", "q", "r", "s", "t", "u", "v", "w",
+   "x", "y", "z", "{", "|", "}", "~", "%7F",
+   "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
+   "%88", "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F",
+   "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
+   "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
+   "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7",
+   "%A8", "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF",
+   "%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7",
+   "%B8", "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF",
+   "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
+   "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF",
+   "%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7",
+   "%D8", "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF",
+   "%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7",
+   "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
+   "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7",
+   "%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF",
+];
+
+
 pub static DEFAULT_ENCODE_SET: [&'static str, ..256] = [
    "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
    "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F",

+ 23 - 57
src/parser.rs

@@ -17,8 +17,8 @@ use encoding::all::UTF_8;
 use super::{
     ParseResult, ErrorHandler, Url, RelativeSchemeData, OtherSchemeData,
     SchemeRelativeUrl, Host, Domain,
-    utf8_percent_encode, percent_encode_byte};
-use encode_sets::{SIMPLE_ENCODE_SET, DEFAULT_ENCODE_SET, USERINFO_ENCODE_SET};
+    utf8_percent_encode, percent_encode};
+use encode_sets::{SIMPLE_ENCODE_SET, DEFAULT_ENCODE_SET, USERINFO_ENCODE_SET, QUERY_ENCODE_SET};
 
 
 macro_rules! is_match(
@@ -278,14 +278,7 @@ fn parse_userinfo<'a>(input: &'a str, parse_error: ErrorHandler)
             },
             '\t' | '\n' | '\r' => try!(parse_error("Invalid character")),
             _ => {
-                if c == '%' {
-                    if !starts_with_2_hex(input.slice_from(i + 1)) {
-                        try!(parse_error("Invalid percent-encoded sequence"));
-                    }
-                } else if !is_url_code_point(c) {
-                    try!(parse_error("Non-URL code point"));
-                }
-
+                try!(check_url_code_point(input, i, c, parse_error));
                 utf8_percent_encode(input.slice(i, next_i),
                                     USERINFO_ENCODE_SET, &mut username);
             }
@@ -301,14 +294,7 @@ fn parse_password(input: &str, parse_error: ErrorHandler) -> ParseResult<String>
         match c {
             '\t' | '\n' | '\r' => try!(parse_error("Invalid character")),
             _ => {
-                if c == '%' {
-                    if !starts_with_2_hex(input.slice_from(i + 1)) {
-                        try!(parse_error("Invalid percent-encoded sequence"));
-                    }
-                } else if !is_url_code_point(c) {
-                    try!(parse_error("Non-URL code point"));
-                }
-
+                try!(check_url_code_point(input, i, c, parse_error));
                 utf8_percent_encode(input.slice(i, next_i),
                                     USERINFO_ENCODE_SET, &mut password);
             }
@@ -463,14 +449,7 @@ fn parse_path<'a>(base_path: Vec<String>, input: &'a str, full_url: bool, in_fil
                 },
                 '\t' | '\n' | '\r' => try!(parse_error("Invalid character")),
                 _ => {
-                    if c == '%' {
-                        if !starts_with_2_hex(input.slice_from(i + 1)) {
-                            try!(parse_error("Invalid percent-encoded sequence"));
-                        }
-                    } else if !is_url_code_point(c) {
-                        try!(parse_error("Non-URL code point"));
-                    }
-
+                    try!(check_url_code_point(input, i, c, parse_error));
                     utf8_percent_encode(input.slice(i, next_i),
                                         DEFAULT_ENCODE_SET, &mut path_part);
                 }
@@ -523,14 +502,7 @@ fn parse_scheme_data<'a>(input: &'a str, parse_error: ErrorHandler)
             },
             '\t' | '\n' | '\r' => try!(parse_error("Invalid character")),
             _ => {
-                if c == '%' {
-                    if !starts_with_2_hex(input.slice_from(i + 1)) {
-                        try!(parse_error("Invalid percent-encoded sequence"));
-                    }
-                } else if !is_url_code_point(c) {
-                    try!(parse_error("Non-URL code point"));
-                }
-
+                try!(check_url_code_point(input, i, c, parse_error));
                 utf8_percent_encode(input.slice(i, next_i),
                                     SIMPLE_ENCODE_SET, &mut scheme_data);
             }
@@ -577,27 +549,14 @@ pub fn parse_query<'a>(input: &'a str, encoding_override: EncodingRef, full_url:
             },
             '\t' | '\n' | '\r' => try!(parse_error("Invalid character")),
             _ => {
-                if c == '%' {
-                    if !starts_with_2_hex(input.slice_from(i + 1)) {
-                        try!(parse_error("Invalid percent-encoded sequence"));
-                    }
-                } else if !is_url_code_point(c) {
-                    try!(parse_error("Non-URL code point"));
-                }
+                try!(check_url_code_point(input, i, c, parse_error));
                 query.push_char(c);
             }
         }
     }
     let query_bytes = encoding_override.encode(query.as_slice(), encoding::EncodeReplace).unwrap();
     let mut query_encoded = String::new();
-    for &byte in query_bytes.iter() {
-        match byte {
-            b'\x00'.. b' ' | b'"' | b'#' | b'<' | b'>' | b'`' | b'~'..b'\xFF'
-            => percent_encode_byte(byte, &mut query_encoded),
-            _
-            => unsafe { query_encoded.push_byte(byte) }
-        }
-    }
+    percent_encode(query_bytes.as_slice(), QUERY_ENCODE_SET, &mut query_encoded);
     Ok((query_encoded, remaining))
 }
 
@@ -608,14 +567,7 @@ pub fn parse_fragment<'a>(input: &'a str, parse_error: ErrorHandler) -> ParseRes
         match c {
             '\t' | '\n' | '\r' => try!(parse_error("Invalid character")),
             _ => {
-                if c == '%' {
-                    if !starts_with_2_hex(input.slice_from(i + 1)) {
-                        try!(parse_error("Invalid percent-encoded sequence"));
-                    }
-                } else if !is_url_code_point(c) {
-                    try!(parse_error("Non-URL code point"));
-                }
-
+                try!(check_url_code_point(input, i, c, parse_error));
                 utf8_percent_encode(input.slice(i, next_i),
                                     SIMPLE_ENCODE_SET, &mut fragment);
             }
@@ -678,6 +630,7 @@ fn is_url_code_point(c: char) -> bool {
 // Last two of each plane: U+__FFFE to U+__FFFF for __ in 00 to 10 hex
 
 
+#[inline]
 fn is_relative_scheme(scheme: &str) -> bool {
     is_match!(scheme, "ftp" | "file" | "gopher" | "http" | "https" | "ws" | "wss")
 }
@@ -713,3 +666,16 @@ impl<'a> Iterator<(uint, char, uint)> for CharRanges<'a> {
         }
     }
 }
+
+#[inline]
+fn check_url_code_point(input: &str, i: uint, c: char, parse_error: ErrorHandler)
+                        -> ParseResult<()> {
+    if c == '%' {
+        if !starts_with_2_hex(input.slice_from(i + 1)) {
+            try!(parse_error("Invalid percent-encoded sequence"));
+        }
+    } else if !is_url_code_point(c) {
+        try!(parse_error("Non-URL code point"));
+    }
+    Ok(())
+}

+ 7 - 1
src/url.rs

@@ -527,7 +527,13 @@ fn to_hex_upper(value: u8) -> u8 {
 
 #[inline]
 fn utf8_percent_encode(input: &str, encode_set: &[&str], output: &mut String) {
-    for byte in input.bytes() {
+    percent_encode(input.as_bytes(), encode_set, output)
+}
+
+
+#[inline]
+fn percent_encode(input: &[u8], encode_set: &[&str], output: &mut String) {
+    for &byte in input.iter() {
         output.push_str(encode_set[byte as uint])
     }
 }