Просмотр исходного кода

Use lookup tables for percent-encoding.

Simon Sapin 12 лет назад
Родитель
Сommit
86fd85478a
4 измененных файлов с 243 добавлено и 38 удалено
  1. 39 0
      make_encode_sets.py
  2. 190 0
      src/encode_sets.rs
  3. 7 7
      src/parser.rs
  4. 7 31
      src/url.rs

+ 39 - 0
make_encode_sets.py

@@ -0,0 +1,39 @@
+# Copyright 2013-2014 Simon Sapin.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+
+# Run as: python make_encode_sets.py > src/encode_sets.rs
+
+
+print('''\
+// Copyright 2013-2014 Simon Sapin.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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', ' "#<>?`@/\\:'),
+]:
+    print(
+        "pub static %s: [&'static str, ..256] = [\n%s\n];\n\n"
+        % (name, '\n'.join(
+            '   ' + ' '.join(
+                '"%s%s",' % ("\\" if chr(b) in '\\"' else "", chr(b))
+                if 0x20 <= b <= 0x7E and chr(b) not in encoded
+                else '"%%%02X",' % b
+                for b in range(s, s + 8)
+            ) for s in range(0, 256, 8))))

+ 190 - 0
src/encode_sets.rs

@@ -0,0 +1,190 @@
+// Copyright 2013-2014 Simon Sapin.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Generated by make_encode_sets.py
+
+pub static SIMPLE_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",
+   " ", "!", "\"", "#", "$", "%", "&", "'",
+   "(", ")", "*", "+", ",", "-", ".", "/",
+   "0", "1", "2", "3", "4", "5", "6", "7",
+   "8", "9", ":", ";", "<", "=", ">", "?",
+   "@", "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", "[", "\\", "]", "^", "_",
+   "`", "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",
+   "%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", "%3F",
+   "@", "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 USERINFO_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", "%3F",
+   "%40", "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 PASSWORD_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", "$", "%", "&", "'",
+   "(", ")", "*", "+", ",", "-", ".", "%2F",
+   "0", "1", "2", "3", "4", "5", "6", "7",
+   "8", "9", ":", ";", "%3C", "=", "%3E", "%3F",
+   "%40", "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", "[", "%5C", "]", "^", "_",
+   "%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 USERNAME_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", "$", "%", "&", "'",
+   "(", ")", "*", "+", ",", "-", ".", "%2F",
+   "0", "1", "2", "3", "4", "5", "6", "7",
+   "8", "9", "%3A", ";", "%3C", "=", "%3E", "%3F",
+   "%40", "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", "[", "%5C", "]", "^", "_",
+   "%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",
+];
+
+

+ 7 - 7
src/parser.rs

@@ -16,8 +16,8 @@ use encoding::all::UTF_8;
 use super::{
     ParseResult, ErrorHandler, Url, RelativeSchemeData, OtherSchemeData,
     SchemeRelativeUrl, Host, Domain,
-    utf8_percent_encode, percent_encode_byte,
-    SimpleEncodeSet, DefaultEncodeSet, UserInfoEncodeSet};
+    utf8_percent_encode, percent_encode_byte};
+use encode_sets::{SIMPLE_ENCODE_SET, DEFAULT_ENCODE_SET, USERINFO_ENCODE_SET};
 
 
 macro_rules! is_match(
@@ -286,7 +286,7 @@ fn parse_userinfo<'a>(input: &'a str, parse_error: ErrorHandler)
                 }
 
                 utf8_percent_encode(input.slice(i, i + c.len_utf8_bytes()),
-                                    UserInfoEncodeSet, &mut username);
+                                    USERINFO_ENCODE_SET, &mut username);
             }
         }
     }
@@ -309,7 +309,7 @@ fn parse_password(input: &str, parse_error: ErrorHandler) -> ParseResult<String>
                 }
 
                 utf8_percent_encode(input.slice(i, i + c.len_utf8_bytes()),
-                                    UserInfoEncodeSet, &mut password);
+                                    USERINFO_ENCODE_SET, &mut password);
             }
         }
     }
@@ -471,7 +471,7 @@ fn parse_path<'a>(base_path: Vec<String>, input: &'a str, full_url: bool, in_fil
                     }
 
                     utf8_percent_encode(input.slice(i, i + c.len_utf8_bytes()),
-                                        DefaultEncodeSet, &mut path_part);
+                                        DEFAULT_ENCODE_SET, &mut path_part);
                 }
             }
         }
@@ -531,7 +531,7 @@ fn parse_scheme_data<'a>(input: &'a str, parse_error: ErrorHandler)
                 }
 
                 utf8_percent_encode(input.slice(i, i + c.len_utf8_bytes()),
-                                    SimpleEncodeSet, &mut scheme_data);
+                                    SIMPLE_ENCODE_SET, &mut scheme_data);
             }
         }
     }
@@ -616,7 +616,7 @@ pub fn parse_fragment<'a>(input: &'a str, parse_error: ErrorHandler) -> ParseRes
                 }
 
                 utf8_percent_encode(input.slice(i, i + c.len_utf8_bytes()),
-                                    SimpleEncodeSet, &mut fragment);
+                                    SIMPLE_ENCODE_SET, &mut fragment);
             }
         }
     }

+ 7 - 31
src/url.rs

@@ -21,7 +21,10 @@ use std::str::from_utf8_lossy;
 use encoding::all::UTF_8;
 use encoding::types::EncodingRef;
 
+use encode_sets::{PASSWORD_ENCODE_SET, USERNAME_ENCODE_SET};
 
+
+mod encode_sets;
 mod parser;
 pub mod form_urlencoded;
 pub mod punycode;
@@ -117,7 +120,7 @@ impl Url {
         match self.scheme_data {
             RelativeSchemeData(SchemeRelativeUrl { ref mut username, .. }) => {
                 username.truncate(0);
-                utf8_percent_encode(input, UsernameEncodeSet, username);
+                utf8_percent_encode(input, USERNAME_ENCODE_SET, username);
                 Ok(())
             },
             OtherSchemeData(_) => Err("Can not set username on non-relative URL.")
@@ -129,7 +132,7 @@ impl Url {
         match self.scheme_data {
             RelativeSchemeData(SchemeRelativeUrl { ref mut password, .. }) => {
                 let mut new_password = String::new();
-                utf8_percent_encode(input, PasswordEncodeSet, &mut new_password);
+                utf8_percent_encode(input, PASSWORD_ENCODE_SET, &mut new_password);
                 *password = Some(new_password);
                 Ok(())
             },
@@ -521,37 +524,10 @@ fn to_hex_upper(value: u8) -> u8 {
 }
 
 
-enum EncodeSet {
-    SimpleEncodeSet,
-    DefaultEncodeSet,
-    UserInfoEncodeSet,
-    PasswordEncodeSet,
-    UsernameEncodeSet
-}
-
-
 #[inline]
-fn utf8_percent_encode(input: &str, encode_set: EncodeSet, output: &mut String) {
-    use Default = self::DefaultEncodeSet;
-    use UserInfo = self::UserInfoEncodeSet;
-    use Password = self::PasswordEncodeSet;
-    use Username = self::UsernameEncodeSet;
+fn utf8_percent_encode(input: &str, encode_set: &[&str], output: &mut String) {
     for byte in input.bytes() {
-        if byte < 0x20 || byte > 0x7E || match byte {
-            b' ' | b'"' | b'#' | b'<' | b'>' | b'?' | b'`'
-            => is_match!(encode_set, Default | UserInfo | Password | Username),
-            b'@'
-            => is_match!(encode_set, UserInfo | Password | Username),
-            b'/' | b'\\'
-            => is_match!(encode_set, Password | Username),
-            b':'
-            => is_match!(encode_set, Username),
-            _ => false,
-        } {
-            percent_encode_byte(byte, output)
-        } else {
-            unsafe { output.push_byte(byte) }
-        }
+        output.push_str(encode_set[byte as uint])
     }
 }