about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/net_url.rs78
1 files changed, 59 insertions, 19 deletions
diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs
index 0d8011f0b0f..ef20807d2f1 100644
--- a/src/libstd/net_url.rs
+++ b/src/libstd/net_url.rs
@@ -263,11 +263,25 @@ fn decode_form_urlencoded(s: ~[u8]) -> hashmap<~str, @dvec<@~str>> {
 
 
 fn split_char_first(s: ~str, c: char) -> (~str, ~str) {
-    let mut v = str::splitn_char(s, c, 1);
-    if v.len() == 1 {
-        return (s, ~"");
+    let len = str::len(s);
+    let mut index = len;
+    let mut match_ = 0;
+    do io::with_str_reader(s) |rdr| {
+        let mut ch : char;
+        while !rdr.eof() {
+            ch = rdr.read_byte() as char;
+            if ch == c {
+                // found a match, adjust markers
+                index = rdr.tell()-1;
+                match_ = 1;
+                break;
+            }
+        }
+    }
+    if index+match_ == len {
+        return (str::slice(s, 0, index), ~"");
     } else {
-        return (vec::shift(v), vec::pop(v));
+        return (str::slice(s, 0, index), str::slice(s, index + match_, str::len(s)));
     }
 }
 
@@ -311,18 +325,30 @@ fn query_to_str(query: query) -> ~str {
     return str::connect(strvec, ~"&");
 }
 
-fn get_scheme(rawurl: ~str) -> option::option<(~str, ~str)> {
+fn get_scheme(rawurl: ~str) -> result::result<(~str, ~str), @~str> {
     for str::each_chari(rawurl) |i,c| {
-        if char::is_alphabetic(c) {
+        alt c {
+          'A' to 'Z' | 'a' to 'z' { again; }
+          '0' to '9' | '+' | '-' | '.' {
+            if i == 0 {
+                return result::err(@~"url: Scheme must begin with a letter.");
+            }
             again;
-        } else if c == ':' && i != 0 {
-            return option::some((rawurl.slice(0,i),
-                              rawurl.slice(i+3,str::len(rawurl))));
-        } else {
-            return option::none;
+          }
+          ':' {
+            if i == 0 {
+                return result::err(@~"url: Scheme cannot be empty.");
+            } else {
+                return result::ok((rawurl.slice(0,i),
+                                rawurl.slice(i+3,str::len(rawurl))));
+            }
+          }
+          _  {
+            return result::err(@~"url: Invalid character in scheme.");
+          }
         }
     };
-    return option::none;
+    return result::ok((copy rawurl, ~""));
 }
 
 /**
@@ -340,10 +366,10 @@ fn get_scheme(rawurl: ~str) -> option::option<(~str, ~str)> {
 
 fn from_str(rawurl: ~str) -> result::result<url, ~str> {
     let mut schm = get_scheme(rawurl);
-    if option::is_none(schm) {
-        return result::err(~"invalid scheme");
+    if result::is_err(schm) {
+        return result::err(copy *result::get_err(schm));
     }
-    let (scheme, rest) = option::unwrap(schm);
+    let (scheme, rest) = result::unwrap(schm);
     let (u, rest) = split_char_first(rest, '@');
     let user = if str::len(rest) == 0 {
         option::none
@@ -422,17 +448,31 @@ impl of to_str::to_str for url {
 #[cfg(test)]
 mod tests {
     #[test]
+    fn test_split_char_first() {
+        let (u,v) = split_char_first(~"hello, sweet world", ',');
+        assert u == ~"hello";
+        assert v == ~" sweet world";
+    }
+
+    #[test]
     fn test_url_parse() {
         let url = ~"http://user:pass@rust-lang.org/doc?s=v#something";
         let u = result::unwrap(from_str(url));
         assert u.scheme == ~"http";
-        assert option::unwrap(u.user).user == ~"user";
-        assert option::unwrap(option::unwrap(u.user).pass) == ~"pass";
+        assert option::unwrap(copy u.user).user == ~"user";
+        assert option::unwrap(copy option::unwrap(copy u.user).pass) == ~"pass";
         assert u.host == ~"rust-lang.org";
         assert u.path == ~"/doc";
-        assert u.query.get(~"s") == ~"v";
-        assert option::unwrap(u.fragment) == "something";
+        assert u.query.find(|kv| kv.first() == ~"s").get().second() == ~"v";
+        assert option::unwrap(copy u.fragment) == ~"something";
     }
+
+    #[test]
+    fn test_invalid_scheme_errors() {
+        assert result::is_err(from_str(~"99://something"));
+        assert result::is_err(from_str(~"://something"));
+    }
+
     #[test]
     fn test_full_url_parse_and_format() {
         let url = ~"http://user:pass@rust-lang.org/doc?s=v#something";