From 1acf6f4051170f72f614a861bdf1a61193053315 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Tue, 28 Mar 2023 23:58:18 -0400 Subject: [PATCH 1/2] Add `Rapid` versioning (ala Gnome, Firefox, Chrome) with single decimal --- src/version/mod.rs | 71 ++++++++++++++++++++++++++++++---- src/version/rapid.rs | 89 +++++++++++++++++++++++++++++++++++++++++++ src/version/semver.rs | 12 +++--- 3 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 src/version/rapid.rs diff --git a/src/version/mod.rs b/src/version/mod.rs index d6c048f..0911f1e 100644 --- a/src/version/mod.rs +++ b/src/version/mod.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; + use { chrono::{offset::Utc, DateTime}, serde::{Deserialize, Serialize}, @@ -5,17 +7,22 @@ use { }; mod gitrev; +mod rapid; mod semver; -pub use {gitrev::GitRev, semver::SemVer}; +pub use {gitrev::GitRev, rapid::Rapid, semver::SemVer}; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub enum Version { Number(u32), + Rapid { + major: u32, + minor: u32, + }, SemVer { - major: u8, - minor: u8, - patch: u8, + major: u32, + minor: u32, + patch: u32, }, Git { hash: String, @@ -49,6 +56,13 @@ impl fmt::Display for Version { }; write!(f, "{v}") } + Self::Rapid { major, minor } => { + let v = Rapid { + major: *major, + minor: *minor, + }; + write!(f, "{v}") + } Self::Git { hash, datetime } => { let v = GitRev { hash: hash.clone(), @@ -70,6 +84,12 @@ impl From for Version { } } +impl From for Version { + fn from(value: Rapid) -> Self { + Self::Rapid { major: value.major, minor: value.minor } + } +} + impl From for Version { fn from(value: GitRev) -> Self { Self::Git { @@ -102,16 +122,26 @@ impl PartialOrd for Version { patch: f, }, ) => (a, b, c).partial_cmp(&(d, e, f)), + ( + Self::Rapid { + major: a, + minor: b, + }, + Self::Rapid { + major: c, + minor: d, + }, + ) => (a, b).partial_cmp(&(c, d)), ( Self::Git { - hash: a, + hash: _a, datetime: b, }, Self::Git { - hash: c, + hash: _c, datetime: d, }, - ) => (a, b).partial_cmp(&(c, d)), + ) => b.partial_cmp(&d), _ => None, } } @@ -134,6 +164,8 @@ impl FromStr for Version { fn from_str(s: &str) -> Result { if let Ok(v) = s.parse::() { Ok(v.into()) + } else if let Ok(v) = s.parse::() { + Ok(v.into()) } else if let Ok(v) = s.parse::() { Ok(v.into()) } else if let Ok(v) = s.parse::() { @@ -143,3 +175,28 @@ impl FromStr for Version { } } } + +impl PartialEq for SemVer { + fn eq(&self, other: &Rapid) -> bool { + self.major == other.major && self.minor == other.minor && self.patch == 0 + } +} + +impl PartialOrd for SemVer { + fn partial_cmp(&self, other: &Rapid) -> Option { + match self.major.partial_cmp(&other.major) { + Some(Ordering::Greater) => Some(Ordering::Greater), + Some(Ordering::Less) => Some(Ordering::Less), + None => None, + Some(Ordering::Equal) => match self.minor.partial_cmp(&other.minor) { + Some(Ordering::Greater) => Some(Ordering::Greater), + Some(Ordering::Less) => Some(Ordering::Less), + None => None, + Some(Ordering::Equal) => match self.patch { + 0 => Some(Ordering::Equal), + _ => Some(Ordering::Greater), + } + } + } + } +} diff --git a/src/version/rapid.rs b/src/version/rapid.rs new file mode 100644 index 0000000..25e2dae --- /dev/null +++ b/src/version/rapid.rs @@ -0,0 +1,89 @@ +use { + serde::{Deserialize, Serialize}, + std::{cmp::Ordering, error::Error, fmt, num::ParseIntError, str::FromStr}, +}; + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Rapid { + pub major: u32, + pub minor: u32, +} + +impl fmt::Display for Rapid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}.{}", self.major, self.minor) + } +} + +impl PartialOrd for Rapid { + fn partial_cmp(&self, other: &Self) -> Option { + match self.major.partial_cmp(&other.major) { + Some(Ordering::Greater) => Some(Ordering::Greater), + Some(Ordering::Less) => Some(Ordering::Less), + Some(Ordering::Equal) => self.minor.partial_cmp(&other.minor), + None => None, + } + } +} + +impl Ord for Rapid { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match self.major.cmp(&other.major) { + Ordering::Greater => Ordering::Greater, + Ordering::Less => Ordering::Less, + Ordering::Equal => self.minor.cmp(&other.minor), + } + } +} + +#[derive(Debug, PartialEq)] +pub struct ParseRapidError; + +impl fmt::Display for ParseRapidError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error parsing Rapid version") + } +} + +impl Error for ParseRapidError {} + +impl From for ParseRapidError { + fn from(_value: ParseIntError) -> Self { + Self + } +} + +impl FromStr for Rapid { + type Err = ParseRapidError; + + fn from_str(s: &str) -> Result { + let split = s.split('.').collect::>(); + match split.len() { + 2 => { + let major = split.first().unwrap().parse::()?; + let minor = split.get(1).unwrap().parse::()?; + Ok(Self { + major, + minor, + }) + } + _ => Err(ParseRapidError), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn parse_semver() { + assert_eq!( + "93.0".parse::(), + Ok(Rapid { + major: 93, + minor: 0, + }) + ); + } +} diff --git a/src/version/semver.rs b/src/version/semver.rs index 474bb31..e4dbc35 100644 --- a/src/version/semver.rs +++ b/src/version/semver.rs @@ -5,9 +5,9 @@ use { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct SemVer { - pub major: u8, - pub minor: u8, - pub patch: u8, + pub major: u32, + pub minor: u32, + pub patch: u32, } impl fmt::Display for SemVer { @@ -70,9 +70,9 @@ impl FromStr for SemVer { let split = s.split('.').collect::>(); match split.len() { 3 => { - let major = split.first().unwrap().parse::()?; - let minor = split.get(1).unwrap().parse::()?; - let patch = split.get(2).unwrap().parse::()?; + let major = split.first().unwrap().parse::()?; + let minor = split.get(1).unwrap().parse::()?; + let patch = split.get(2).unwrap().parse::()?; Ok(Self { major, minor, From e8aead53650c2e2007fa21306bbf3ddb8928c365 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Wed, 29 Mar 2023 00:18:49 -0400 Subject: [PATCH 2/2] Implement PartialEq and PartialOrd between SemVer and Rapid versioning --- src/version/mod.rs | 43 +++++++++++++++++++++---------------------- src/version/rapid.rs | 5 +---- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/version/mod.rs b/src/version/mod.rs index 0911f1e..d37217b 100644 --- a/src/version/mod.rs +++ b/src/version/mod.rs @@ -1,9 +1,7 @@ -use std::cmp::Ordering; - use { chrono::{offset::Utc, DateTime}, serde::{Deserialize, Serialize}, - std::{error::Error, fmt, str::FromStr}, + std::{cmp::Ordering, error::Error, fmt, str::FromStr}, }; mod gitrev; @@ -86,7 +84,10 @@ impl From for Version { impl From for Version { fn from(value: Rapid) -> Self { - Self::Rapid { major: value.major, minor: value.minor } + Self::Rapid { + major: value.major, + minor: value.minor, + } } } @@ -111,27 +112,20 @@ impl PartialOrd for Version { match (self, other) { (Self::Number(s), Self::Number(o)) => s.partial_cmp(o), ( + Self::SemVer { + major, + minor, + patch, + }, Self::SemVer { major: a, minor: b, patch: c, }, - Self::SemVer { - major: d, - minor: e, - patch: f, - }, - ) => (a, b, c).partial_cmp(&(d, e, f)), - ( - Self::Rapid { - major: a, - minor: b, - }, - Self::Rapid { - major: c, - minor: d, - }, - ) => (a, b).partial_cmp(&(c, d)), + ) => (major, minor, patch).partial_cmp(&(a, b, c)), + (Self::Rapid { major, minor }, Self::Rapid { major: a, minor: b }) => { + (major, minor).partial_cmp(&(a, b)) + } ( Self::Git { hash: _a, @@ -142,6 +136,11 @@ impl PartialOrd for Version { datetime: d, }, ) => b.partial_cmp(&d), + ( + Self::SemVer { major, minor, patch }, + Self::Rapid { major: a, minor: b }, + ) => SemVer { major: *major, minor: *minor, patch: *patch } + .partial_cmp(&Rapid { major: *a, minor: *b }), _ => None, } } @@ -195,8 +194,8 @@ impl PartialOrd for SemVer { Some(Ordering::Equal) => match self.patch { 0 => Some(Ordering::Equal), _ => Some(Ordering::Greater), - } - } + }, + }, } } } diff --git a/src/version/rapid.rs b/src/version/rapid.rs index 25e2dae..53a667e 100644 --- a/src/version/rapid.rs +++ b/src/version/rapid.rs @@ -62,10 +62,7 @@ impl FromStr for Rapid { 2 => { let major = split.first().unwrap().parse::()?; let minor = split.get(1).unwrap().parse::()?; - Ok(Self { - major, - minor, - }) + Ok(Self { major, minor }) } _ => Err(ParseRapidError), }