about summary refs log tree commit diff
path: root/src/libsyntax/crateid.rs
diff options
context:
space:
mode:
authorLuis de Bethencourt <luis@debethencourt.com>2013-12-28 12:16:48 -0500
committerLuis de Bethencourt <luis@debethencourt.com>2013-12-29 15:25:32 -0500
commitf872c472788ca00a88d56ec5d6b3ff73a8dcc005 (patch)
treef123e7cd655e31c8c3ea271e3530cde42cb59d04 /src/libsyntax/crateid.rs
parent4bc09713dfea7e53095c9a64a9e4ff90868b5b2a (diff)
downloadrust-f872c472788ca00a88d56ec5d6b3ff73a8dcc005.tar.gz
rust-f872c472788ca00a88d56ec5d6b3ff73a8dcc005.zip
Rename PkgId to CrateId
Diffstat (limited to 'src/libsyntax/crateid.rs')
-rw-r--r--src/libsyntax/crateid.rs186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/libsyntax/crateid.rs b/src/libsyntax/crateid.rs
new file mode 100644
index 00000000000..0bb1eec512b
--- /dev/null
+++ b/src/libsyntax/crateid.rs
@@ -0,0 +1,186 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// 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.
+
+/// CrateIds identify crates and include the crate name and optionally a path
+/// and version. In the full form, they look like relative URLs. Example:
+/// `github.com/mozilla/rust#std:1.0` would be a package ID with a path of
+/// `gitub.com/mozilla/rust` and a crate name of `std` with a version of
+/// `1.0`. If no crate name is given after the hash, the name is inferred to
+/// be the last component of the path. If no version is given, it is inferred
+/// to be `0.0`.
+#[deriving(Clone, Eq)]
+pub struct CrateId {
+    /// A path which represents the codes origin. By convention this is the
+    /// URL, without `http://` or `https://` prefix, to the crate's repository
+    path: ~str,
+    /// The name of the crate.
+    name: ~str,
+    /// The version of the crate.
+    version: Option<~str>,
+}
+
+impl ToStr for CrateId {
+    fn to_str(&self) -> ~str {
+        let version = match self.version {
+            None => "0.0",
+            Some(ref version) => version.as_slice(),
+        };
+        if self.path == self.name || self.path.ends_with(format!("/{}", self.name)) {
+            format!("{}\\#{}", self.path, version)
+        } else {
+            format!("{}\\#{}:{}", self.path, self.name, version)
+        }
+    }
+}
+
+impl FromStr for CrateId {
+    fn from_str(s: &str) -> Option<CrateId> {
+        let pieces: ~[&str] = s.splitn('#', 1).collect();
+        let path = pieces[0].to_owned();
+
+        if path.starts_with("/") || path.ends_with("/") ||
+            path.starts_with(".") || path.is_empty() {
+            return None;
+        }
+
+        let path_pieces: ~[&str] = path.rsplitn('/', 1).collect();
+        let inferred_name = path_pieces[0];
+
+        let (name, version) = if pieces.len() == 1 {
+            (inferred_name.to_owned(), None)
+        } else {
+            let hash_pieces: ~[&str] = pieces[1].splitn(':', 1).collect();
+            let (hash_name, hash_version) = if hash_pieces.len() == 1 {
+                ("", hash_pieces[0])
+            } else {
+                (hash_pieces[0], hash_pieces[1])
+            };
+
+            let name = if !hash_name.is_empty() {
+                hash_name.to_owned()
+            } else {
+                inferred_name.to_owned()
+            };
+
+            let version = if !hash_version.is_empty() {
+                Some(hash_version.to_owned())
+            } else {
+                None
+            };
+
+            (name, version)
+        };
+
+        Some(CrateId {
+            path: path,
+            name: name,
+            version: version,
+        })
+    }
+}
+
+impl CrateId {
+    pub fn version_or_default<'a>(&'a self) -> &'a str {
+        match self.version {
+            None => "0.0",
+            Some(ref version) => version.as_slice(),
+        }
+    }
+}
+
+#[test]
+fn bare_name() {
+    let crateid: CrateId = from_str("foo").expect("valid crateid");
+    assert_eq!(crateid.name, ~"foo");
+    assert_eq!(crateid.version, None);
+    assert_eq!(crateid.path, ~"foo");
+}
+
+#[test]
+fn bare_name_single_char() {
+    let crateid: CrateId = from_str("f").expect("valid crateid");
+    assert_eq!(crateid.name, ~"f");
+    assert_eq!(crateid.version, None);
+    assert_eq!(crateid.path, ~"f");
+}
+
+#[test]
+fn empty_crateid() {
+    let crateid: Option<CrateId> = from_str("");
+    assert!(crateid.is_none());
+}
+
+#[test]
+fn simple_path() {
+    let crateid: CrateId = from_str("example.com/foo/bar").expect("valid crateid");
+    assert_eq!(crateid.name, ~"bar");
+    assert_eq!(crateid.version, None);
+    assert_eq!(crateid.path, ~"example.com/foo/bar");
+}
+
+#[test]
+fn simple_version() {
+    let crateid: CrateId = from_str("foo#1.0").expect("valid crateid");
+    assert_eq!(crateid.name, ~"foo");
+    assert_eq!(crateid.version, Some(~"1.0"));
+    assert_eq!(crateid.path, ~"foo");
+}
+
+#[test]
+fn absolute_path() {
+    let crateid: Option<CrateId> = from_str("/foo/bar");
+    assert!(crateid.is_none());
+}
+
+#[test]
+fn path_ends_with_slash() {
+    let crateid: Option<CrateId> = from_str("foo/bar/");
+    assert!(crateid.is_none());
+}
+
+#[test]
+fn path_and_version() {
+    let crateid: CrateId = from_str("example.com/foo/bar#1.0").expect("valid crateid");
+    assert_eq!(crateid.name, ~"bar");
+    assert_eq!(crateid.version, Some(~"1.0"));
+    assert_eq!(crateid.path, ~"example.com/foo/bar");
+}
+
+#[test]
+fn single_chars() {
+    let crateid: CrateId = from_str("a/b#1").expect("valid crateid");
+    assert_eq!(crateid.name, ~"b");
+    assert_eq!(crateid.version, Some(~"1"));
+    assert_eq!(crateid.path, ~"a/b");
+}
+
+#[test]
+fn missing_version() {
+    let crateid: CrateId = from_str("foo#").expect("valid crateid");
+    assert_eq!(crateid.name, ~"foo");
+    assert_eq!(crateid.version, None);
+    assert_eq!(crateid.path, ~"foo");
+}
+
+#[test]
+fn path_and_name() {
+    let crateid: CrateId = from_str("foo/rust-bar#bar:1.0").expect("valid crateid");
+    assert_eq!(crateid.name, ~"bar");
+    assert_eq!(crateid.version, Some(~"1.0"));
+    assert_eq!(crateid.path, ~"foo/rust-bar");
+}
+
+#[test]
+fn empty_name() {
+    let crateid: CrateId = from_str("foo/bar#:1.0").expect("valid crateid");
+    assert_eq!(crateid.name, ~"bar");
+    assert_eq!(crateid.version, Some(~"1.0"));
+    assert_eq!(crateid.path, ~"foo/bar");
+}