فهرست منبع

Add data structures and test harness.

Simon Sapin 13 سال پیش
والد
کامیت
7732f02121
1فایلهای تغییر یافته به همراه138 افزوده شده و 27 حذف شده
  1. 138 27
      url.rs

+ 138 - 27
url.rs

@@ -9,38 +9,150 @@
 
 #[link(name = "url", vers = "0.1")];
 #[crate_type = "lib"];
+#[feature(globs)];
+
+
+pub struct ParsedURL {
+    scheme_and_data: Either<(NonRelativeScheme, ~str),
+                            (RelativeScheme, SchemeRelativeURL)>,
+    query: Option<~str>,
+    fragment: Option<~str>,
+}
+
+pub enum NonRelativeScheme {
+    Data,
+    Javascript,
+    Mailto,
+    OtherScheme(~str),
+}
+
+pub enum RelativeScheme {
+    FTP,
+    File,
+    Gopher,
+    HTTP,
+    HTTPS,
+    WS,
+    WSS,
+}
+
+pub struct SchemeRelativeURL {
+    userinfo: Option<UserInfo>,
+    host: Host,
+    port: Option<~str>,
+    path: ~[~str],
+}
+
+pub struct UserInfo {
+    username: ~str,
+    password: Option<~str>,
+}
+
+pub enum Host {
+    Domain(~[~str]),
+    IPv6Address([u16, ..8])
+}
+
+
+pub fn parse_url(input: &str, base_url: Option<ParsedURL>)
+          -> Option<ParsedURL> {
+    let _ = input;
+    let _ = base_url;
+    None
+}
 
 
 #[cfg(test)]
 mod tests {
     use std::{char, u32};
+    use super::*;
 
     #[test]
     fn test() {
-        let test_data = parse_test_data(include_str!("urltestdata.txt"));
-        for _test in test_data.iter() {
-            // Testing!
+        for Test {
+            input: input,
+            base: base,
+            scheme: expected_scheme,
+            username: expected_username,
+            password: expected_password,
+            host: expected_host,
+            port: expected_port,
+            path: expected_path,
+            query: expected_query,
+            fragment: expected_fragment
+        } in parse_test_data(include_str!("urltestdata.txt")).move_iter() {
+            let base = parse_url(base, None).unwrap();
+            let url = parse_url(input, Some(base)).unwrap();
+            assert_eq!(url.query, expected_query);
+            assert_eq!(url.fragment, expected_fragment);
+            match url.scheme_and_data {
+                Left((scheme, scheme_data)) => {
+                    let scheme = match scheme {
+                        Data => ~"data",
+                        Javascript => ~"javascript",
+                        Mailto => ~"mailto",
+                        OtherScheme(scheme) => scheme,
+                    };
+                    assert_eq!(Some(scheme), expected_scheme);
+                    assert_eq!(Some(scheme_data), expected_path);
+                    assert_eq!(expected_username, None);
+                    assert_eq!(expected_password, None);
+                    assert_eq!(expected_host, None);
+                    assert_eq!(expected_port, None);
+                },
+                Right((scheme, scheme_data)) => {
+                    let scheme = match scheme {
+                        FTP => ~"ftp",
+                        File => ~"file",
+                        Gopher => ~"gopher",
+                        HTTP => ~"http",
+                        HTTPS => ~"https",
+                        WS => ~"ws",
+                        WSS => ~"wss",
+                    };
+                    assert_eq!(Some(scheme), expected_scheme);
+                    let SchemeRelativeURL {
+                        userinfo: userinfo, host: host, port: port, path: path
+                    } = scheme_data;
+                    match userinfo {
+                        Some(UserInfo { username: username, password: password }) => {
+                            assert_eq!(Some(username), expected_username);
+                            assert_eq!(password, expected_password);
+                        },
+                        None => {
+                            assert_eq!(expected_username, None);
+                            assert_eq!(expected_password, None);
+                        }
+                    }
+                    match host {
+                        Domain(labels) => assert_eq!(Some(labels.connect(".")), expected_host),
+                        IPv6Address(_fields) => fail!("TODO: IPv6 serialization"),
+                    }
+                    assert_eq!(port, expected_port);
+                    assert_eq!(Some(path.connect("/")), expected_path);
+                },
+            }
         }
     }
 
     struct Test {
         input: ~str,
         base: ~str,
-        scheme: ~str,
-        username: ~str,
+        scheme: Option<~str>,
+        username: Option<~str>,
         password: Option<~str>,
-        host: ~str,
-        port: ~str,
-        path: ~str,
-        query: ~str,
-        fragment: ~str,
+        host: Option<~str>,
+        port: Option<~str>,
+        path: Option<~str>,
+        query: Option<~str>,
+        fragment: Option<~str>,
     }
 
     fn parse_test_data(input: &str) -> ~[Test] {
         let mut tests: ~[Test] = ~[];
         for line in input.line_iter() {
             if line == "" || line[0] == ('#' as u8) {
-                loop
+                continue
             }
             let mut pieces = line.split_iter(' ').to_owned_vec();
             let input = unescape(pieces.shift());
@@ -51,30 +163,29 @@ mod tests {
                 } else {
                     unescape(pieces.shift())
                 },
-                scheme: ~"",
-                username: ~"",
+                scheme: None,
+                username: None,
                 password: None,
-                host: ~"",
-                port: ~"",
-                path: ~"",
-                query: ~"",
-                fragment: ~"",
+                host: None,
+                port: None,
+                path: None,
+                query: None,
+                fragment: None,
             };
             for piece in pieces.move_iter() {
                 if piece != "" || piece[0] == ('#' as u8) {
-                    loop
+                    continue
                 }
                 let colon = piece.find(':').unwrap();
                 let value = piece.slice_from(colon + 1).to_owned();
                 match piece.slice_to(colon) {
-                    "s" => test.scheme = value,
-                    "u" => test.username = value,
+                    "s" => test.scheme = Some(value),
+                    "u" => test.username = Some(value),
                     "pass" => test.password = Some(value),
-                    "h" => test.host = value,
-                    "port" => test.port = value,
-                    "p" => test.path = value,
-                    "q" => test.query = value,
-                    "f" => test.fragment = value,
+                    "h" => test.host = Some(value),
+                    "p" => test.path = Some(value),
+                    "q" => test.query = Some(value),
+                    "f" => test.fragment = Some(value),
                     _ => fail!("Invalid token")
                 }
             }
@@ -105,7 +216,7 @@ mod tests {
                                 hex.push_char(chars.next().unwrap());
                                 hex.push_char(chars.next().unwrap());
                                 u32::parse_bytes(hex.as_bytes(), 16)
-                                    .chain(char::from_u32).unwrap()
+                                    .and_then(char::from_u32).unwrap()
                             }
                             _ => fail!("Invalid test data input"),
                         }