diff options
| author | Daniel Patterson <dbp@riseup.net> | 2012-07-25 22:40:31 -0400 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2012-08-03 11:28:19 -0700 |
| commit | d60dd6be87a1647db5434e9bf94994e4c1a8a68d (patch) | |
| tree | 266bafd75f32b2122391cfb7b00365a2b80f8829 /src/libstd | |
| parent | e349201bc26c2581e948aae53ac7701c34bef80c (diff) | |
std::net::url making scheme parsing compliant with rfc, give appropriate error messages, better split fn
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/net_url.rs | 78 |
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"; |
