diff options
| author | Zack Corr <zack@z0w0.me> | 2013-01-16 21:59:37 +1000 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2013-02-15 18:04:10 -0800 |
| commit | 226b61ba5f30e0ecb0799626a010161f3ce0b72d (patch) | |
| tree | ed15c6860e9e94096eb2078df4d692f4d88f6b12 /src/libcore | |
| parent | 71d34a8872491f37011aa14c866a95165fc45f99 (diff) | |
rustpkg: Add package script parsing
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/core.rc | 1 | ||||
| -rw-r--r-- | src/libcore/semver.rs | 227 |
2 files changed, 228 insertions, 0 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 5b6c40e09ef..6169ac24c05 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -169,6 +169,7 @@ pub mod reflect; pub mod condition; pub mod logging; pub mod util; +pub mod semver; /* Reexported core operators */ diff --git a/src/libcore/semver.rs b/src/libcore/semver.rs new file mode 100644 index 00000000000..5a739772d1e --- /dev/null +++ b/src/libcore/semver.rs @@ -0,0 +1,227 @@ +// Copyright 2012 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. + +//! Semver parsing and logic + +use io; +use io::{ReaderUtil}; +use option::{Option, Some, None}; +use uint; +use str; +use to_str::ToStr; +use char; + +pub struct Version { + major: uint, + minor: uint, + patch: uint, + tag: Option<~str>, +} + +impl Version: ToStr { + #[inline(always)] + pure fn to_str() -> ~str { + let suffix = match copy self.tag { + Some(tag) => ~"-" + tag, + None => ~"" + }; + + fmt!("%u.%u.%u%s", self.major, self.minor, self.patch, suffix) + } +} + +fn read_whitespace(rdr: io::Reader, ch: char) -> char { + let mut nch = ch; + + while char::is_whitespace(nch) { + nch = rdr.read_char(); + } + + nch +} + +fn parse_reader(rdr: io::Reader) -> Option<(Version, char)> { + fn read_digits(rdr: io::Reader, ch: char) -> Option<(uint, char)> { + let mut buf = ~""; + let mut nch = ch; + + while nch != -1 as char { + match nch { + '0' .. '9' => buf += str::from_char(nch), + _ => break + } + + nch = rdr.read_char(); + } + + do uint::from_str(buf).chain_ref |&i| { + Some((i, nch)) + } + } + + fn read_tag(rdr: io::Reader) -> Option<(~str, char)> { + let mut ch = rdr.read_char(); + let mut buf = ~""; + + while ch != -1 as char { + match ch { + '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '-' => { + buf += str::from_char(ch); + } + _ => break + } + + ch = rdr.read_char(); + } + + if buf == ~"" { return None; } + else { Some((buf, ch)) } + } + + let ch = read_whitespace(rdr, rdr.read_char()); + let (major, ch) = match read_digits(rdr, ch) { + None => return None, + Some(item) => item + }; + + if ch != '.' { return None; } + + let (minor, ch) = match read_digits(rdr, rdr.read_char()) { + None => return None, + Some(item) => item + }; + + if ch != '.' { return None; } + + let (patch, ch) = match read_digits(rdr, rdr.read_char()) { + None => return None, + Some(item) => item + }; + let (tag, ch) = if ch == '-' { + match read_tag(rdr) { + None => return None, + Some((tag, ch)) => (Some(tag), ch) + } + } else { + (None, ch) + }; + + Some((Version { major: major, minor: minor, patch: patch, tag: tag }, + ch)) +} + +pub fn parse(s: ~str) -> Option<Version> { + do io::with_str_reader(s) |rdr| { + do parse_reader(rdr).chain_ref |&item| { + let (version, ch) = item; + + if read_whitespace(rdr, ch) != -1 as char { + None + } else { + Some(version) + } + } + } +} + +#[test] +fn test_parse() { + assert parse("") == None; + assert parse(" ") == None; + assert parse("1") == None; + assert parse("1.2") == None; + assert parse("1.2") == None; + assert parse("1") == None; + assert parse("1.2") == None; + assert parse("1.2.3-") == None; + assert parse("a.b.c") == None; + assert parse("1.2.3 abc") == None; + + assert parse("1.2.3") == Some({ + major: 1u, + minor: 2u, + patch: 3u, + tag: None, + }); + assert parse(" 1.2.3 ") == Some({ + major: 1u, + minor: 2u, + patch: 3u, + tag: None, + }); + assert parse("1.2.3-alpha1") == Some({ + major: 1u, + minor: 2u, + patch: 3u, + tag: Some("alpha1") + }); + assert parse(" 1.2.3-alpha1 ") == Some({ + major: 1u, + minor: 2u, + patch: 3u, + tag: Some("alpha1") + }); +} + +#[test] +fn test_eq() { + assert parse("1.2.3") == parse("1.2.3"); + assert parse("1.2.3-alpha1") == parse("1.2.3-alpha1"); +} + +#[test] +fn test_ne() { + assert parse("0.0.0") != parse("0.0.1"); + assert parse("0.0.0") != parse("0.1.0"); + assert parse("0.0.0") != parse("1.0.0"); + assert parse("1.2.3-alpha") != parse("1.2.3-beta"); +} + +#[test] +fn test_lt() { + assert parse("0.0.0") < parse("1.2.3-alpha2"); + assert parse("1.0.0") < parse("1.2.3-alpha2"); + assert parse("1.2.0") < parse("1.2.3-alpha2"); + assert parse("1.2.3") < parse("1.2.3-alpha2"); + assert parse("1.2.3-alpha1") < parse("1.2.3-alpha2"); + + assert !(parse("1.2.3-alpha2") < parse("1.2.3-alpha2")); +} + +#[test] +fn test_le() { + assert parse("0.0.0") <= parse("1.2.3-alpha2"); + assert parse("1.0.0") <= parse("1.2.3-alpha2"); + assert parse("1.2.0") <= parse("1.2.3-alpha2"); + assert parse("1.2.3") <= parse("1.2.3-alpha2"); + assert parse("1.2.3-alpha1") <= parse("1.2.3-alpha2"); + assert parse("1.2.3-alpha2") <= parse("1.2.3-alpha2"); +} + +#[test] +fn test_gt() { + assert parse("1.2.3-alpha2") > parse("0.0.0"); + assert parse("1.2.3-alpha2") > parse("1.0.0"); + assert parse("1.2.3-alpha2") > parse("1.2.0"); + assert parse("1.2.3-alpha2") > parse("1.2.3"); + assert parse("1.2.3-alpha2") > parse("1.2.3-alpha1"); + + assert !(parse("1.2.3-alpha2") > parse("1.2.3-alpha2")); +} + +#[test] +fn test_ge() { + assert parse("1.2.3-alpha2") >= parse("0.0.0"); + assert parse("1.2.3-alpha2") >= parse("1.0.0"); + assert parse("1.2.3-alpha2") >= parse("1.2.0"); + assert parse("1.2.3-alpha2") >= parse("1.2.3"); + assert parse("1.2.3-alpha2") >= parse("1.2.3-alpha1"); + assert parse("1.2.3-alpha2") >= parse("1.2.3-alpha2"); +} |
