summaryrefslogtreecommitdiff
path: root/semver-parser/src/common.rs
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2019-01-02 21:14:10 -0800
committerDaniel Mueller <deso@posteo.net>2019-01-02 21:14:10 -0800
commitecf3474223ca3d16a10f12dc2272e3b0ed72c1bb (patch)
tree03134a683791176b49ef5c92e8d6acd24c3b5a9b /semver-parser/src/common.rs
parent686f61b75055ecb02baf9d9449525ae447a3bed1 (diff)
downloadnitrocli-ecf3474223ca3d16a10f12dc2272e3b0ed72c1bb.tar.gz
nitrocli-ecf3474223ca3d16a10f12dc2272e3b0ed72c1bb.tar.bz2
Update nitrokey crate to 0.2.3
This change updates the nitrokey crate to version 0.2.3. This version bumps the rand crate used to 0.6.1, which in turn requires an additional set of dependencies. Import subrepo nitrokey/:nitrokey at b3e2adc5bb1300441ca74cc7672617c042f3ea31 Import subrepo rand/:rand at 73613ff903512e9503e41cc8ba9eae76269dc598 Import subrepo rustc_version/:rustc_version at 0294f2ba2018bf7be672abd53db351ce5055fa02 Import subrepo semver-parser/:semver-parser at 750da9b11a04125231b1fb293866ca036845acee Import subrepo semver/:semver at 5eb6db94fa03f4d5c64a625a56188f496be47598
Diffstat (limited to 'semver-parser/src/common.rs')
-rw-r--r--semver-parser/src/common.rs66
1 files changed, 66 insertions, 0 deletions
diff --git a/semver-parser/src/common.rs b/semver-parser/src/common.rs
new file mode 100644
index 0000000..267b4d9
--- /dev/null
+++ b/semver-parser/src/common.rs
@@ -0,0 +1,66 @@
+use version::Identifier;
+use recognize::{Recognize, Alt, OneOrMore, Inclusive, OneByte};
+use std::str::from_utf8;
+
+// by the time we get here, we know that it's all valid characters, so this doesn't need to return
+// a result or anything
+fn parse_meta(s: &str) -> Vec<Identifier> {
+ // Originally, I wanted to implement this method via calling parse, but parse is tolerant of
+ // leading zeroes, and we want anything with leading zeroes to be considered alphanumeric, not
+ // numeric. So the strategy is to check with a recognizer first, and then call parse once
+ // we've determined that it's a number without a leading zero.
+ s.split(".")
+ .map(|part| {
+ // another wrinkle: we made sure that any number starts with a
+ // non-zero. But there's a problem: an actual zero is a number, yet
+ // gets left out by this heuristic. So let's also check for the
+ // single, lone zero.
+ if is_alpha_numeric(part) {
+ Identifier::AlphaNumeric(part.to_string())
+ } else {
+ // we can unwrap here because we know it is only digits due to the regex
+ Identifier::Numeric(part.parse().unwrap())
+ }
+ }).collect()
+}
+
+// parse optional metadata (preceded by the prefix character)
+pub fn parse_optional_meta(s: &[u8], prefix_char: u8)-> Result<(Vec<Identifier>, usize), String> {
+ if let Some(len) = prefix_char.p(s) {
+ let start = len;
+ if let Some(len) = letters_numbers_dash_dot(&s[start..]) {
+ let end = start + len;
+ Ok((parse_meta(from_utf8(&s[start..end]).unwrap()), end))
+ } else {
+ Err("Error parsing prerelease".to_string())
+ }
+ } else {
+ Ok((Vec::new(), 0))
+ }
+}
+
+pub fn is_alpha_numeric(s: &str) -> bool {
+ if let Some((_val, len)) = numeric_identifier(s.as_bytes()) {
+ // Return true for number with leading zero
+ // Note: doing it this way also handily makes overflow fail over.
+ len != s.len()
+ } else {
+ true
+ }
+}
+
+// Note: could plumb overflow error up to return value as Result
+pub fn numeric_identifier(s: &[u8]) -> Option<(u64, usize)> {
+ if let Some(len) = Alt(b'0', OneOrMore(Inclusive(b'0'..b'9'))).p(s) {
+ from_utf8(&s[0..len]).unwrap().parse().ok().map(|val| (val, len))
+ } else {
+ None
+ }
+}
+
+pub fn letters_numbers_dash_dot(s: &[u8]) -> Option<usize> {
+ OneOrMore(OneByte(|c| c == b'-' || c == b'.' ||
+ (b'0' <= c && c <= b'9') ||
+ (b'a' <= c && c <= b'z') ||
+ (b'A' <= c && c <= b'Z'))).p(s)
+}