diff --git a/src/prerelease.rs b/src/prerelease.rs index 164beb2..6f45ff8 100644 --- a/src/prerelease.rs +++ b/src/prerelease.rs @@ -4,14 +4,87 @@ use { std::{cmp, fmt, num::NonZeroU16, str}, }; +static MAX_U10: u16 = 1024; + #[derive(Clone, Copy, Debug, Deserialize, Serialize)] +/// A specification for non-production releases pub enum PreRelease { Alpha(Option), Beta(Option), RC(Option), + /// `PreRelease::None` is equivalent to a normal release None, } +impl PreRelease { + pub fn is_prerelease(&self) -> bool { + match self { + Self::None => false, + _ => true, + } + } + + pub fn is_alpha(&self) -> bool { + match self { + Self::Alpha(_) => true, + _ => false, + } + } + + pub fn is_beta(&self) -> bool { + match self { + Self::Beta(_) => true, + _ => false, + } + } + + pub fn is_rc(&self) -> bool { + match self { + Self::RC(_) => true, + _ => false, + } + } + + pub fn number(&self) -> Option { + match self { + Self::Alpha(n) | Self::Beta(n) | Self::RC(n) => n.map(|x| x.into()), + _ => None, + } + } + + /// Increments the numerical portion of the prerelease spec + /// # Errors + /// Returns `Error::Range` if the operation would overflow + pub fn increment(&mut self) -> Result<(), Error> { + match self { + Self::Alpha(n) | Self::Beta(n) | Self::RC(n) => match n { + Some(num) => { + if u16::from(*num) >= MAX_U10 { + return Err(Error::Range); + } else { + *num = num.saturating_add(1); + } + } + None => *n = Some(NonZeroU16::new(2).unwrap()), + }, + _ => {} + } + Ok(()) + } + + /// Promotes the prerelease spec to a higher type eg. alpha->beta or beta->rc + /// If the spec is already Self::RC(_) then it becomes a regular release ie. + /// `PreRelease::None` + pub fn promote(&mut self) { + match self { + Self::Alpha(_) => *self = Self::Beta(None), + Self::Beta(_) => *self = Self::RC(None), + Self::RC(_) => *self = Self::None, + _ => {} + } + } +} + impl fmt::Display for PreRelease { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self {