Kaynağa Gözat

Turns out [Ascii] isn’t that useful. Switch to str.

Simon Sapin 12 yıl önce
ebeveyn
işleme
2bb8cf786b
4 değiştirilmiş dosya ile 146 ekleme ve 151 silme
  1. 44 45
      parser.rs
  2. 20 22
      punycode.rs
  3. 8 10
      tests.rs
  4. 74 74
      url.rs

+ 44 - 45
parser.rs

@@ -1,5 +1,5 @@
-use std::ascii::{Ascii, StrAsciiExt};
 use std::str;
+use std::ascii::StrAsciiExt;
 
 use encoding;
 use encoding::EncodingRef;
@@ -36,7 +36,7 @@ pub fn parse_url(input: &str, base_url: Option<&URL>) -> ParseResult<URL> {
     let (scheme_result, remaining) = parse_scheme(input);
     match scheme_result {
         Some(scheme) => {
-            if scheme.as_str_ascii() == "file" {
+            if scheme.as_slice() == "file" {
                 // Relative state?
                 match base_url {
                     Some(base) if scheme == base.scheme => {
@@ -44,9 +44,9 @@ pub fn parse_url(input: &str, base_url: Option<&URL>) -> ParseResult<URL> {
                         parse_relative_url(scheme, remaining, base)
                     },
                     _ => parse_relative_url(scheme, remaining, &URL {
-                        scheme: ~[], query: None, fragment: None,
+                        scheme: ~"", query: None, fragment: None,
                         scheme_data: RelativeSchemeData(SchemeRelativeURL {
-                            userinfo: None, host: Domain(~[]), port: ~[], path: ~[]
+                            userinfo: None, host: Domain(~[]), port: ~"", path: ~[]
                         })
                     }),
                 }
@@ -80,7 +80,7 @@ pub fn parse_url(input: &str, base_url: Option<&URL>) -> ParseResult<URL> {
 }
 
 
-fn parse_scheme<'a>(input: &'a str) -> (Option<~[Ascii]>, &'a str) {
+fn parse_scheme<'a>(input: &'a str) -> (Option<~str>, &'a str) {
     if input.is_empty() || !is_ascii_alpha(input[0]) {
         return (None, input)
     }
@@ -89,7 +89,7 @@ fn parse_scheme<'a>(input: &'a str) -> (Option<~[Ascii]>, &'a str) {
         match input[i] as char {
             'a'..'z' | 'A'..'Z' | '0'..'9' | '+' | '-' | '.' => (),
             ':' => return (
-                Some(ascii_nocheck!(input.slice_to(i)).to_lower()),
+                Some(input.slice_to(i).to_ascii_lower()),
                 input.slice_from(i + 1),
             ),
             _ => return (None, input),
@@ -100,7 +100,7 @@ fn parse_scheme<'a>(input: &'a str) -> (Option<~[Ascii]>, &'a str) {
 }
 
 
-fn parse_absolute_url<'a>(scheme: ~[Ascii], input: &'a str) -> ParseResult<URL> {
+fn parse_absolute_url<'a>(scheme: ~str, input: &'a str) -> ParseResult<URL> {
     // Authority first slash state
     let remaining = skip_slashes(input);
     // Authority state
@@ -120,14 +120,14 @@ fn parse_absolute_url<'a>(scheme: ~[Ascii], input: &'a str) -> ParseResult<URL>
 }
 
 
-fn parse_relative_url<'a>(scheme: ~[Ascii], input: &'a str, base: &URL) -> ParseResult<URL> {
+fn parse_relative_url<'a>(scheme: ~str, input: &'a str, base: &URL) -> ParseResult<URL> {
     match base.scheme_data {
         OtherSchemeData(_) => Err("Relative URL with a non-relative-scheme base"),
         RelativeSchemeData(ref base_scheme_data) => if input.is_empty() {
             Ok(URL { scheme: scheme, scheme_data: base.scheme_data.clone(),
                      query: base.query.clone(), fragment: None })
         } else {
-            let in_file_scheme = scheme.as_str_ascii() == "file";
+            let in_file_scheme = scheme.as_slice() == "file";
             match input[0] as char {
                 '/' | '\\' => {
                     // Relative slash state
@@ -152,7 +152,7 @@ fn parse_relative_url<'a>(scheme: ~[Ascii], input: &'a str, base: &URL) -> Parse
                             let (path, remaining) = parse_path_start(
                                 remaining, /* full_url= */ true, in_file_scheme);
                             let scheme_data = RelativeSchemeData(SchemeRelativeURL {
-                                userinfo: None, host: host, port: ~[], path: path });
+                                userinfo: None, host: host, port: ~"", path: path });
                             let (query, fragment) = parse_query_and_fragment(remaining);
                             Ok(URL { scheme: scheme, scheme_data: scheme_data,
                                      query: query, fragment: fragment })
@@ -165,7 +165,7 @@ fn parse_relative_url<'a>(scheme: ~[Ascii], input: &'a str, base: &URL) -> Parse
                             ~[], input.slice_from(1), /* full_url= */ true, in_file_scheme);
                         let scheme_data = RelativeSchemeData(if in_file_scheme {
                             SchemeRelativeURL {
-                                userinfo: None, host: Domain(~[]), port: ~[], path: path
+                                userinfo: None, host: Domain(~[]), port: ~"", path: path
                             }
                         } else {
                             SchemeRelativeURL {
@@ -204,7 +204,7 @@ fn parse_relative_url<'a>(scheme: ~[Ascii], input: &'a str, base: &URL) -> Parse
                          (RelativeSchemeData(SchemeRelativeURL {
                             userinfo: None,
                             host: Domain(~[]),
-                            port: ~[],
+                            port: ~"",
                             path: path
                         }), remaining)
                     } else {
@@ -269,7 +269,7 @@ fn parse_userinfo<'a>(input: &'a str) -> (Option<UserInfo>, &'a str) {
 
 
 fn parse_userinfo_inner<'a>(input: &'a str) -> UserInfo {
-    let mut username = ~[];
+    let mut username = ~"";
     let mut i = 0;
     loop {
         if i >= input.len() {
@@ -299,7 +299,7 @@ fn parse_userinfo_inner<'a>(input: &'a str) -> UserInfo {
             }
         }
     }
-    let mut password = ~[];
+    let mut password = ~"";
     while i < input.len() {
         match input[i] as char {
             '\t' | '\n' | '\r' => {
@@ -325,7 +325,7 @@ fn parse_userinfo_inner<'a>(input: &'a str) -> UserInfo {
 }
 
 
-fn parse_hostname<'a>(input: &'a str, scheme: &[Ascii]) -> ParseResult<(Host, ~[Ascii], &'a str)> {
+fn parse_hostname<'a>(input: &'a str, scheme: &str) -> ParseResult<(Host, ~str, &'a str)> {
     let mut i = 0;
     let mut inside_square_brackets = false;
     let mut host_input = ~"";
@@ -355,23 +355,23 @@ fn parse_hostname<'a>(input: &'a str, scheme: &[Ascii]) -> ParseResult<(Host, ~[
     }
     match Host::parse(host_input) {
         Err(message) => Err(message),
-        Ok(host) => Ok((host, ~[], input.slice_from(i))),
+        Ok(host) => Ok((host, ~"", input.slice_from(i))),
     }
 }
 
 
-fn parse_port<'a>(input: &'a str, scheme: &[Ascii]) -> ParseResult<(~[Ascii], &'a str)> {
-    let mut port = ~[];
+fn parse_port<'a>(input: &'a str, scheme: &str) -> ParseResult<(~str, &'a str)> {
+    let mut port = ~"";
     let mut has_initial_zero = false;
     let mut i = 0;
     while i < input.len() {
         match input[i] as char {
-            '1' .. '9' => port.push(ascii_nocheck!(input[i])),
+            '1' .. '9' => unsafe { str::raw::push_byte(&mut port, input[i]) },
             '0' => {
                 if port.is_empty() {
                     has_initial_zero = true
                 } else {
-                    port.push(ascii_nocheck!(input[i]))
+                    unsafe { str::raw::push_byte(&mut port, input[i]) }
                 }
             },
             '/' | '\\' | '?' | '#' => break,
@@ -381,9 +381,9 @@ fn parse_port<'a>(input: &'a str, scheme: &[Ascii]) -> ParseResult<(~[Ascii], &'
         i += 1;
     }
     if port.is_empty() && has_initial_zero {
-        port.push(ascii_nocheck!('0'))
+        port.push_str("0")
     }
-    match (scheme.as_str_ascii(), port.as_str_ascii()) {
+    match (scheme, port.as_slice()) {
         ("ftp", "21") | ("gopher", "70") | ("http", "80") |
         ("https", "443") | ("ws", "80") | ("wss", "443")
         => port.clear(),
@@ -417,7 +417,7 @@ fn parse_file_host<'a>(input: &'a str) -> ParseResult<(Host, &'a str)> {
 
 
 fn parse_path_start<'a>(input: &'a str, full_url: bool, in_file_scheme: bool)
-           -> (~[~[Ascii]], &'a str) {
+           -> (~[~str], &'a str) {
     let mut i = 0;
     // Relative path start state
     if !input.is_empty() {
@@ -434,13 +434,13 @@ fn parse_path_start<'a>(input: &'a str, full_url: bool, in_file_scheme: bool)
 }
 
 
-fn parse_path<'a>(base_path: ~[~[Ascii]], input: &'a str, full_url: bool, in_file_scheme: bool)
-           -> (~[~[Ascii]], &'a str) {
+fn parse_path<'a>(base_path: ~[~str], input: &'a str, full_url: bool, in_file_scheme: bool)
+           -> (~[~str], &'a str) {
     // Relative path state
     let mut path = base_path;
     let mut i = 0;
     loop {
-        let mut path_part = ~[];
+        let mut path_part = ~"";
         let mut ends_with_slash = false;
         while i < input.len() {
             match input[i] as char {
@@ -475,27 +475,29 @@ fn parse_path<'a>(base_path: ~[~[Ascii]], input: &'a str, full_url: bool, in_fil
                 }
             }
         }
-        let lower = path_part.as_str_ascii().to_ascii_lower();
+        let lower = path_part.to_ascii_lower();
         match lower.as_slice() {
             ".." | ".%2e" | "%2e." | "%2e%2e" => {
                 path.pop_opt();
                 if !ends_with_slash {
-                    path.push(~[]);
+                    path.push(~"");
                 }
             },
             "." | "%2e" => {
                 if !ends_with_slash {
-                    path.push(~[]);
+                    path.push(~"");
                 }
             },
             _ => {
                 if in_file_scheme
                    && path.is_empty()
                    && path_part.len() == 2
-                   && is_ascii_alpha(path_part[0].to_byte())
-                   && path_part[1].to_char() == '|' {
+                   && is_ascii_alpha(path_part[0])
+                   && path_part[1] == ('|' as u8) {
                     // Windows drive letter quirk
-                    path_part[1] = ascii_nocheck!(':');
+                    unsafe {
+                        str::raw::as_owned_vec(&mut path_part)[1] = ':' as u8
+                    }
                 }
                 path.push(path_part)
             }
@@ -508,8 +510,8 @@ fn parse_path<'a>(base_path: ~[~[Ascii]], input: &'a str, full_url: bool, in_fil
 }
 
 
-fn parse_scheme_data<'a>(input: &'a str) -> (~[Ascii], &'a str) {
-    let mut scheme_data = ~[];
+fn parse_scheme_data<'a>(input: &'a str) -> (~str, &'a str) {
+    let mut scheme_data = ~"";
     let mut i = 0;
     while i < input.len() {
         match input[i] as char {
@@ -537,7 +539,7 @@ fn parse_scheme_data<'a>(input: &'a str) -> (~[Ascii], &'a str) {
 }
 
 
-fn parse_query_and_fragment(input: &str) -> (Option<~[Ascii]>, Option<~[Ascii]>) {
+fn parse_query_and_fragment(input: &str) -> (Option<~str>, Option<~str>) {
     if input.is_empty() {
         (None, None)
     } else {
@@ -557,7 +559,7 @@ fn parse_query_and_fragment(input: &str) -> (Option<~[Ascii]>, Option<~[Ascii]>)
 
 
 fn parse_query<'a>(input: &'a str, encoding_override: EncodingRef, full_url: bool)
-               -> (~[Ascii], Option<&'a str>) {
+               -> (~str, Option<&'a str>) {
     let mut query = ~"";
     let mut i = 0;
     let mut remaining = None;
@@ -587,21 +589,21 @@ fn parse_query<'a>(input: &'a str, encoding_override: EncodingRef, full_url: boo
         }
     }
     let query_bytes = encoding_override.encode(query, encoding::EncodeReplace).unwrap();
-    let mut query_encoded = ~[];
+    let mut query_encoded = ~"";
     for &byte in query_bytes.iter() {
         match byte {
             0x00 .. 0x20 | 0x22 | 0x23 | 0x3C | 0x3E | 0x60 | 0x7E .. 0xFF
             => percent_encode_byte(byte, &mut query_encoded),
             _
-            => query_encoded.push(ascii_nocheck!(byte))
+            => unsafe { str::raw::push_byte(&mut query_encoded, byte) }
         }
     }
     (query_encoded, remaining)
 }
 
 
-fn parse_fragment<'a>(input: &'a str) -> ~[Ascii] {
-    let mut fragment = ~[];
+fn parse_fragment<'a>(input: &'a str) -> ~str {
+    let mut fragment = ~"";
     let mut i = 0;
     while i < input.len() {
         match input[i] as char {
@@ -680,9 +682,6 @@ fn is_url_code_point(c: char) -> bool {
 // Last two of each plane: U+__FFFE to U+__FFFF for __ in 01 to 10 hex
 
 
-fn is_relative_scheme(scheme: &[Ascii]) -> bool {
-    match scheme.as_str_ascii() {
-        "ftp" | "file" | "gopher" | "http" | "https" | "ws" | "wss" => true,
-        _ => false
-    }
+fn is_relative_scheme(scheme: &str) -> bool {
+    is_match!(scheme, "ftp" | "file" | "gopher" | "http" | "https" | "ws" | "wss")
 }

+ 20 - 22
punycode.rs

@@ -9,7 +9,7 @@
 
 use std::u32;
 use std::char;
-use std::ascii::Ascii;
+use std::str;
 
 
 // Bootstring parameters for Punycode
@@ -40,32 +40,32 @@ fn adapt(mut delta: u32, num_points: u32, first_time: bool) -> u32 {
 /// Return None on malformed input or overflow.
 /// Overflow can only happen on inputs that take more than
 /// 63 encoded bytes, the DNS limit on domain name labels.
-pub fn decode(input: &[Ascii]) -> Option<~[char]> {
+pub fn decode(input: &str) -> Option<~[char]> {
     // Handle "basic" (ASCII) code points.
     // They are encoded as-is befor the last delimiter, if any.
-    let (mut output, input) = match input.rposition_elem(&DELIMITER.to_ascii()) {
+    let (mut output, input) = match input.rfind(DELIMITER) {
         None => (~[], input),
         Some(position) => (
-            input.slice_to(position).map(|a| a.to_char()),
+            input.slice_to(position).chars().to_owned_vec(),
             if position > 0 { input.slice_from(position + 1) } else { input }
         )
     };
     let mut code_point = INITIAL_N;
     let mut bias = INITIAL_BIAS;
     let mut i = 0;
-    let mut iter = input.iter();
+    let mut iter = input.bytes();
     loop {
         let previous_i = i;
         let mut weight = 1;
         let mut k = BASE;
-        let mut ascii = match iter.next() {
+        let mut byte = match iter.next() {
             None => break,
-            Some(ascii) => ascii,
+            Some(byte) => byte,
         };
         // Decode a generalized variable-length integer into delta,
         // which gets added to i.
         loop {
-            let digit = match ascii.to_byte() {
+            let digit = match byte {
                 byte @ 0x30 .. 0x39 => byte - 0x30 + 26,  // 0..9
                 byte @ 0x41 .. 0x5A => byte - 0x41,  // A..Z
                 byte @ 0x61 .. 0x7A => byte - 0x61,  // a..z
@@ -86,9 +86,9 @@ pub fn decode(input: &[Ascii]) -> Option<~[char]> {
             }
             weight *= BASE - t;
             k += BASE;
-            ascii = match iter.next() {
+            byte = match iter.next() {
                 None => return None,  // End of input before the end of this delta
-                Some(ascii) => ascii,
+                Some(byte) => byte,
             };
         }
         let length = output.len() as u32;
@@ -114,15 +114,15 @@ pub fn decode(input: &[Ascii]) -> Option<~[char]> {
 /// Convert Unicode to Punycode.
 /// Return None on overflow, which can only happen on inputs that would take more than
 /// 63 encoded bytes, the DNS limit on domain name labels.
-pub fn encode(input: &[char]) -> Option<~[Ascii]> {
+pub fn encode(input: &[char]) -> Option<~str> {
     // Handle "basic" (ASCII) code points. They are encoded as-is.
-    let mut output = input.iter().filter_map(|&c|
-        if c.is_ascii() { Some(unsafe { c.to_ascii_nocheck() }) }
-        else { None }
+    let output_bytes = input.iter().filter_map(|&c|
+        if c.is_ascii() { Some(c as u8) } else { None }
     ).to_owned_vec();
+    let mut output = unsafe { str::raw::from_utf8_owned(output_bytes) };
     let basic_length = output.len() as u32;
     if basic_length > 0 {
-        output.push('-'.to_ascii())
+        output.push_str("-")
     }
     let mut code_point = INITIAL_N;
     let mut delta = 0;
@@ -160,11 +160,11 @@ pub fn encode(input: &[char]) -> Option<~[Ascii]> {
                         break
                     }
                     let value = t + ((q - t) % (BASE - t));
-                    output.push(value_to_digit(value));
+                    value_to_digit(value, &mut output);
                     q = (q - t) / (BASE - t);
                     k += BASE;
                 }
-                output.push(value_to_digit(q));
+                value_to_digit(q, &mut output);
                 bias = adapt(delta, processed + 1, processed == basic_length);
                 delta = 0;
                 processed += 1;
@@ -178,25 +178,24 @@ pub fn encode(input: &[char]) -> Option<~[Ascii]> {
 
 
 #[inline]
-fn value_to_digit(value: u32) -> Ascii {
+fn value_to_digit(value: u32, output: &mut ~str) {
     let code_point = match value {
         0 .. 25 => value + 0x61,  // a..z
         26 .. 35 => value - 26 + 0x30,  // 0..9
         _ => fail!()
     };
-    unsafe { (code_point as u8).to_ascii_nocheck() }
+    unsafe { str::raw::push_byte(output, code_point as u8) }
 }
 
 
 #[cfg(test)]
 mod tests {
     use super::{decode, encode};
-    use std::ascii::AsciiCast;
     use std::str::from_chars;
     use extra::json::{from_str, List, Object, String};
 
     fn one_test(description: &str, decoded: &str, encoded: &str) {
-        match decode(encoded.to_ascii()) {
+        match decode(encoded) {
             None => fail!("Decoding {:?} failed.", encoded),
             Some(result) => {
                 let result = from_chars(result);
@@ -209,7 +208,6 @@ mod tests {
         match encode(decoded.chars().to_owned_vec()) {
             None => fail!("Encoding {:?} failed.", decoded),
             Some(result) => {
-                let result = result.as_str_ascii();
                 assert!(result.as_slice() == encoded,
                         format!("Incorrect encoding of {:?}:\n   {:?}\n!= {:?}\n{}",
                                 decoded, result.as_slice(), encoded, description))

+ 8 - 10
tests.rs

@@ -41,33 +41,31 @@ fn test_url_parsing() {
             Err(message) => fail!("Error parsing URL {:?}: {}", input, message)
         };
 
-        assert_eq!(Some(scheme.as_str_ascii().to_owned()), expected_scheme);
+        assert_eq!(Some(scheme), expected_scheme);
         match scheme_data {
             RelativeSchemeData(SchemeRelativeURL { userinfo, host, port, path }) => {
                 let (username, password) = match userinfo {
                     None => (~"", None),
-                    Some(UserInfo { username, password }) => (
-                        username.as_str_ascii().to_owned(),
-                        password.map(|p| p.as_str_ascii().to_owned())),
+                    Some(UserInfo { username, password }) => (username, password),
                 };
                 assert_eq!(username, expected_username);
                 assert_eq!(password, expected_password);
                 let host = host.serialize();
-                assert_eq!(host.as_str_ascii().to_owned(), expected_host)
-                assert_eq!(port.as_str_ascii().to_owned(), expected_port);
-                assert_eq!(Some("/" + path.map(|p| p.as_str_ascii().to_owned()).connect("/")),
+                assert_eq!(host, expected_host)
+                assert_eq!(port, expected_port);
+                assert_eq!(Some("/" + path.connect("/")),
                            expected_path);
             },
             OtherSchemeData(scheme_data) => {
-                assert_eq!(Some(scheme_data.as_str_ascii().to_owned()), expected_path);
+                assert_eq!(Some(scheme_data), expected_path);
                 assert_eq!(~"", expected_username);
                 assert_eq!(None, expected_password);
                 assert_eq!(~"", expected_host);
                 assert_eq!(~"", expected_port);
             },
         }
-        assert_eq!(query.map(|p| "?" + p.as_str_ascii().to_owned()), expected_query);
-        assert_eq!(fragment.map(|p| "#" + p.as_str_ascii().to_owned()), expected_fragment);
+        assert_eq!(query.map(|p| "?" + p), expected_query);
+        assert_eq!(fragment.map(|p| "#" + p), expected_fragment);
     }
 }
 

+ 74 - 74
url.rs

@@ -11,12 +11,13 @@
 #[crate_type = "lib"];
 #[feature(macro_rules)];
 
+
 extern mod encoding;
 
 #[cfg(test)]
 extern mod extra;
 
-use std::ascii::Ascii;
+use std::str;
 
 use encoding::EncodingRef;
 use encoding::Encoding;
@@ -33,35 +34,35 @@ mod tests;
 
 #[deriving(Clone)]
 pub struct URL {
-    scheme: ~[Ascii],
+    scheme: ~str,
     scheme_data: SchemeData,
-    query: Option<~[Ascii]>,  // parse_form_urlencoded() parses this into ~[(~str, ~str)]
-    fragment: Option<~[Ascii]>,
+    query: Option<~str>,  // parse_form_urlencoded() parses this into ~[(~str, ~str)]
+    fragment: Option<~str>,
 }
 
 #[deriving(Clone)]
 pub enum SchemeData {
     RelativeSchemeData(SchemeRelativeURL),
-    OtherSchemeData(~[Ascii])
+    OtherSchemeData(~str)
 }
 
 #[deriving(Clone)]
 pub struct SchemeRelativeURL {
     userinfo: Option<UserInfo>,
     host: Host,
-    port: ~[Ascii],
-    path: ~[~[Ascii]],
+    port: ~str,
+    path: ~[~str],
 }
 
 #[deriving(Clone)]
 pub struct UserInfo {
-    username: ~[Ascii],
-    password: Option<~[Ascii]>,
+    username: ~str,
+    password: Option<~str>,
 }
 
 #[deriving(Clone)]
 pub enum Host {
-    Domain(~[~[Ascii]]),
+    Domain(~[~str]),
     IPv6(IPv6Address)
 }
 
@@ -91,62 +92,62 @@ impl URL {
         parser::parse_url(input, base_url)
     }
 
-    pub fn serialize(&self) -> ~[Ascii] {
+    pub fn serialize(&self) -> ~str {
         let mut result = self.serialize_no_fragment();
         match self.fragment {
             None => (),
             Some(ref fragment) => {
-                result.push('#'.to_ascii());
-                result.push_all(fragment.as_slice());
+                result.push_str("#");
+                result.push_str(fragment.as_slice());
             }
         }
         result
     }
 
-    pub fn serialize_no_fragment(&self) -> ~[Ascii] {
+    pub fn serialize_no_fragment(&self) -> ~str {
         let mut result = self.scheme.to_owned();
-        result.push(':'.to_ascii());
+        result.push_str(":");
         match self.scheme_data {
             RelativeSchemeData(SchemeRelativeURL {
                 ref userinfo, ref host, ref port, ref path
             }) => {
-                result.push_all("//".to_ascii());
+                result.push_str("//");
                 match userinfo {
                     &None => (),
                     &Some(UserInfo { ref username, ref password })
                     => if username.len() > 0 || password.is_some() {
-                        result.push_all(username.as_slice());
+                        result.push_str(username.as_slice());
                         match password {
                             &None => (),
                             &Some(ref password) => {
-                                result.push(':'.to_ascii());
-                                result.push_all(password.as_slice());
+                                result.push_str(":");
+                                result.push_str(password.as_slice());
                             }
                         }
-                        result.push('@'.to_ascii());
+                        result.push_str("@");
                     }
                 }
-                result.push_all(host.serialize());
+                result.push_str(host.serialize());
                 if port.len() > 0 {
-                    result.push(':'.to_ascii());
-                    result.push_all(port.as_slice());
+                    result.push_str(":");
+                    result.push_str(port.as_slice());
                 }
                 if path.len() > 0 {
                     for path_part in path.iter() {
-                        result.push('/'.to_ascii());
-                        result.push_all(path_part.as_slice());
+                        result.push_str("/");
+                        result.push_str(path_part.as_slice());
                     }
                 } else {
-                    result.push('/'.to_ascii());
+                    result.push_str("/");
                 }
             },
-            OtherSchemeData(ref data) => result.push_all(data.as_slice()),
+            OtherSchemeData(ref data) => result.push_str(data.as_slice()),
         }
         match self.query {
             None => (),
             Some(ref query) => {
-                result.push('?'.to_ascii());
-                result.push_all(query.as_slice());
+                result.push_str("?");
+                result.push_str(query.as_slice());
             }
         }
         result
@@ -168,16 +169,16 @@ impl Host {
                 Err("Invalid IPv6 address")
             }
         } else {
-            let mut percent_encoded = ~[];
+            let mut percent_encoded = ~"";
             utf8_percent_encode(input, SimpleEncodeSet, &mut percent_encoded);
-            let bytes = percent_decode(percent_encoded);
+            let bytes = percent_decode(percent_encoded.as_bytes());
             let decoded = UTF_8.decode(bytes, encoding::DecodeReplace).unwrap();
             let mut labels = ~[];
             for label in decoded.split(&['.', '\u3002', '\uFF0E', '\uFF61']) {
                 // TODO: Remove this check and use IDNA "domain to ASCII"
                 // TODO: switch to .map(domain_label_to_ascii).collect() then.
                 if label.is_ascii() {
-                    labels.push(unsafe { label.to_ascii_nocheck() }.to_owned())
+                    labels.push(label.to_owned())
                 } else {
                     return Err("Non-ASCII domains (IDNA) are not supported yet.")
                 }
@@ -186,13 +187,13 @@ impl Host {
         }
     }
 
-    pub fn serialize(&self) -> ~[Ascii] {
+    pub fn serialize(&self) -> ~str {
         match *self {
-            Domain(ref labels) => labels.connect_vec(&'.'.to_ascii()),
+            Domain(ref labels) => labels.connect("."),
             IPv6(ref address) => {
-                let mut result = ~['['.to_ascii()];
-                result.push_all(address.serialize());
-                result.push(']'.to_ascii());
+                let mut result = ~"[";
+                result.push_str(address.serialize());
+                result.push_str("]");
                 result
             }
         }
@@ -317,15 +318,15 @@ impl IPv6Address {
         Some(IPv6Address { pieces: pieces })
     }
 
-    pub fn serialize(&self) -> ~[Ascii] {
-        let mut output = ~[];
+    pub fn serialize(&self) -> ~str {
+        let mut output = ~"";
         let (compress_start, compress_end) = longest_zero_sequence(&self.pieces);
         let mut i = 0;
         while i < 8 {
             if i == compress_start {
-                output.push(':'.to_ascii());
+                output.push_str(":");
                 if i == 0 {
-                    output.push(':'.to_ascii());
+                    output.push_str(":");
                 }
                 if compress_end < 8 {
                     i = compress_end;
@@ -333,11 +334,9 @@ impl IPv6Address {
                     break;
                 }
             }
-            let hex = self.pieces[i].to_str_radix(16);
-            // No need to check that hex digits are ASCII
-            output.push_all(unsafe { hex.to_ascii_nocheck() });
+            output.push_str(self.pieces[i].to_str_radix(16));
             if i < 7 {
-                output.push(':'.to_ascii());
+                output.push_str(":");
             }
             i += 1;
         }
@@ -387,13 +386,12 @@ fn from_hex(byte: u8) -> Option<u8> {
 }
 
 #[inline]
-fn to_hex_upper(value: u8) -> Ascii {
-    let digit = match value {
+fn to_hex_upper(value: u8) -> u8 {
+    match value {
         0 .. 9 => value + 0x30,
         10 .. 15 => value - 10 + 0x41,
         _ => fail!()
-    };
-    unsafe { digit.to_ascii_nocheck() }
+    }
 }
 
 
@@ -407,12 +405,12 @@ enum EncodeSet {
 
 
 #[inline]
-fn utf8_percent_encode(input: &str, encode_set: EncodeSet, output: &mut ~[Ascii]) {
+fn utf8_percent_encode(input: &str, encode_set: EncodeSet, output: &mut ~str) {
     use Default = self::DefaultEncodeSet;
     use UserInfo = self::UserInfoEncodeSet;
     use Password = self::PasswordEncodeSet;
     use Username = self::UsernameEncodeSet;
-    for &byte in input.as_bytes().iter() {
+    for byte in input.bytes() {
         if byte < 0x20 || byte > 0x7E || match byte as char {
             ' ' | '"' | '#' | '<' | '>' | '?' | '`'
             => is_match!(encode_set, Default | UserInfo | Password | Username),
@@ -426,27 +424,30 @@ fn utf8_percent_encode(input: &str, encode_set: EncodeSet, output: &mut ~[Ascii]
         } {
             percent_encode_byte(byte, output)
         } else {
-            output.push(unsafe { byte.to_ascii_nocheck() })  // Already checked
+            unsafe { str::raw::push_byte(output, byte) }
         }
     }
 }
 
 
 #[inline]
-fn percent_encode_byte(byte: u8, output: &mut ~[Ascii]) {
-    output.push_all(['%'.to_ascii(), to_hex_upper(byte >> 4), to_hex_upper(byte & 0x0F)])
+fn percent_encode_byte(byte: u8, output: &mut ~str) {
+    unsafe {
+        str::raw::push_bytes(output, [
+            '%' as u8, to_hex_upper(byte >> 4), to_hex_upper(byte & 0x0F)
+        ])
+    }
 }
 
 
 #[inline]
-fn percent_decode(input: &[Ascii]) -> ~[u8] {
+fn percent_decode(input: &[u8]) -> ~[u8] {
     let mut output = ~[];
     let mut i = 0u;
     while i < input.len() {
         let c = input[i];
-        if c == '%'.to_ascii() && i + 2 < input.len() {
-            match (from_hex(input[i + 1].to_byte()),
-                   from_hex(input[i + 2].to_byte())) {
+        if c == ('%' as u8) && i + 2 < input.len() {
+            match (from_hex(input[i + 1]), from_hex(input[i + 2])) {
                 (Some(h), Some(l)) => {
                     output.push(h * 0x10 + l);
                     i += 3;
@@ -456,28 +457,28 @@ fn percent_decode(input: &[Ascii]) -> ~[u8] {
             }
         }
 
-        output.push(c.to_byte());
+        output.push(c);
         i += 1;
     }
     output
 }
 
 
-pub fn parse_form_urlencoded(input: &[Ascii],
+pub fn parse_form_urlencoded(input: &str,
                              encoding_override: Option<EncodingRef>,
                              use_charset: bool,
                              mut isindex: bool)
                           -> ~[(~str, ~str)] {
     let mut encoding_override = encoding_override.unwrap_or(UTF_8 as EncodingRef);
     let mut pairs = ~[];
-    for string in input.split(|&c| c == '&'.to_ascii()) {
+    for string in input.split('&') {
         if string.len() > 0 {
-            let (name, value) = match string.position_elem(&'='.to_ascii()) {
+            let (name, value) = match string.find('=') {
                 Some(position) => (string.slice_to(position), string.slice_from(position + 1)),
-                None => if isindex { (&[], string) } else { (string, &[]) }
+                None => if isindex { ("", string) } else { (string, "") }
             };
-            let name = name.as_str_ascii().replace("+", " ");
-            let value = value.as_str_ascii().replace("+", " ");
+            let name = name.replace("+", " ");
+            let value = value.replace("+", " ");
             if use_charset && name.as_slice() == "_charset_" {
                 match encoding_from_whatwg_label(value) {
                     Some(encoding) => encoding_override = encoding,
@@ -491,8 +492,7 @@ pub fn parse_form_urlencoded(input: &[Ascii],
 
     #[inline]
     fn decode(input: &~str, encoding_override: EncodingRef) -> ~str {
-        // No need to check as input comes from &[Ascii].as_str_ascii().replace("+", " ")
-        let bytes = percent_decode(unsafe { input.as_slice().to_ascii_nocheck() });
+        let bytes = percent_decode(input.as_bytes());
         encoding_override.decode(bytes, encoding::DecodeReplace).unwrap()
     }
 
@@ -509,9 +509,9 @@ pub fn parse_form_urlencoded(input: &[Ascii],
 
 pub fn serialize_form_urlencoded(pairs: ~[(~str, ~str)],
                                  encoding_override: Option<EncodingRef>)
-                              -> ~[Ascii] {
+                              -> ~str {
     #[inline]
-    fn byte_serialize(input: &str, output: &mut ~[Ascii],
+    fn byte_serialize(input: &str, output: &mut ~str,
                      encoding_override: Option<EncodingRef>) {
         let keep_alive;
         let input = match encoding_override {
@@ -524,20 +524,20 @@ pub fn serialize_form_urlencoded(pairs: ~[(~str, ~str)],
 
         for byte in input.iter() {
             match *byte {
-                0x20 => output.push('+'.to_ascii()),
+                0x20 => output.push_str("+"),
                 0x2A | 0x2D | 0x2E | 0x30 .. 0x39 | 0x41 .. 0x5A | 0x5F | 0x61 .. 0x7A
-                => output.push(unsafe { byte.to_ascii_nocheck() }),
+                => unsafe { str::raw::push_byte(output, *byte) },
                 _ => percent_encode_byte(*byte, output),
             }
         }
     }
 
-    let mut output = ~[];
+    let mut output = ~"";
     for &(ref name, ref value) in pairs.iter() {
         if output.len() > 0 {
-            output.push('&'.to_ascii());
+            output.push_str("&");
             byte_serialize(name.as_slice(), &mut output, encoding_override);
-            output.push('='.to_ascii());
+            output.push_str("=");
             byte_serialize(value.as_slice(), &mut output, encoding_override);
         }
     }