rabbitmq_versioning/
prerelease.rs1use std::cmp::Ordering;
10use std::fmt;
11
12use serde::{Deserialize, Serialize};
13
14use crate::errors::Error;
15
16#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub enum Prerelease {
18 Alpha(String),
19 Beta(String),
20 Rc(String),
21}
22
23impl Prerelease {
24 pub fn alpha(identifier: impl Into<String>) -> Self {
25 Prerelease::Alpha(identifier.into())
26 }
27
28 pub fn beta(identifier: impl Into<String>) -> Self {
29 Prerelease::Beta(identifier.into())
30 }
31
32 pub fn rc(identifier: impl Into<String>) -> Self {
33 Prerelease::Rc(identifier.into())
34 }
35
36 pub fn is_alpha(&self) -> bool {
37 matches!(self, Prerelease::Alpha(_))
38 }
39
40 pub fn is_beta(&self) -> bool {
41 matches!(self, Prerelease::Beta(_))
42 }
43
44 pub fn is_rc(&self) -> bool {
45 matches!(self, Prerelease::Rc(_))
46 }
47
48 pub fn identifier(&self) -> &str {
49 match self {
50 Prerelease::Alpha(s) | Prerelease::Beta(s) | Prerelease::Rc(s) => s,
51 }
52 }
53
54 pub(crate) fn parse(s: &str, full_version: &str) -> Result<Self, Error> {
55 let parts: Vec<&str> = s.split('.').collect();
56 if parts.len() != 2 {
57 return Err(Error::InvalidVersion(full_version.to_string()));
58 }
59
60 let identifier = parts[1];
61 if identifier.is_empty() {
62 return Err(Error::InvalidVersion(full_version.to_string()));
63 }
64
65 match parts[0].to_lowercase().as_str() {
66 "alpha" => Ok(Prerelease::Alpha(identifier.to_string())),
67 "beta" => Ok(Prerelease::Beta(identifier.to_string())),
68 "rc" => Ok(Prerelease::Rc(identifier.to_string())),
69 _ => Err(Error::InvalidVersion(full_version.to_string())),
70 }
71 }
72}
73
74impl fmt::Display for Prerelease {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 Prerelease::Alpha(s) => write!(f, "alpha.{}", s),
78 Prerelease::Beta(s) => write!(f, "beta.{}", s),
79 Prerelease::Rc(s) => write!(f, "rc.{}", s),
80 }
81 }
82}
83
84fn compare_prerelease_identifiers(a: &str, b: &str) -> Ordering {
85 match (a.parse::<u32>(), b.parse::<u32>()) {
86 (Ok(na), Ok(nb)) => na.cmp(&nb),
87 _ => a.cmp(b),
88 }
89}
90
91impl Ord for Prerelease {
92 fn cmp(&self, other: &Self) -> Ordering {
93 match (self, other) {
94 (Prerelease::Alpha(a), Prerelease::Alpha(b)) => compare_prerelease_identifiers(a, b),
95 (Prerelease::Alpha(_), _) => Ordering::Less,
96 (_, Prerelease::Alpha(_)) => Ordering::Greater,
97 (Prerelease::Beta(a), Prerelease::Beta(b)) => compare_prerelease_identifiers(a, b),
98 (Prerelease::Beta(_), Prerelease::Rc(_)) => Ordering::Less,
99 (Prerelease::Rc(_), Prerelease::Beta(_)) => Ordering::Greater,
100 (Prerelease::Rc(a), Prerelease::Rc(b)) => compare_prerelease_identifiers(a, b),
101 }
102 }
103}
104
105impl PartialOrd for Prerelease {
106 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
107 Some(self.cmp(other))
108 }
109}