update_package/
version.rs1use omaha_client::version::Version as SemanticVersion;
8use serde::de::{self, Visitor};
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10use std::convert::Infallible;
11use std::fmt;
12use std::str::FromStr;
13
14struct SystemVersionVisitor;
15
16impl Visitor<'_> for SystemVersionVisitor {
17 type Value = SystemVersion;
18
19 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
20 formatter.write_str("a string")
21 }
22
23 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
24 where
25 E: de::Error,
26 {
27 Ok(SystemVersion::from_str(v).unwrap())
28 }
29}
30
31#[derive(Clone, Debug, Eq, PartialEq)]
32pub enum SystemVersion {
34 Opaque(String),
36 Semantic(SemanticVersion),
38}
39
40impl SystemVersion {
41 pub fn is_empty(&self) -> bool {
43 if let SystemVersion::Opaque(value) = self { value.is_empty() } else { false }
44 }
45}
46
47impl PartialOrd for SystemVersion {
48 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
49 let my_version = match &self {
50 SystemVersion::Opaque(_) => return None,
51 SystemVersion::Semantic(ver) => ver,
52 };
53
54 let other_version = match other {
55 SystemVersion::Opaque(_) => return None,
56 SystemVersion::Semantic(ver) => ver,
57 };
58
59 my_version.partial_cmp(other_version)
60 }
61}
62
63impl<'de> Deserialize<'de> for SystemVersion {
65 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
66 where
67 D: Deserializer<'de>,
68 {
69 deserializer.deserialize_str(SystemVersionVisitor)
70 }
71}
72
73impl Serialize for SystemVersion {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: Serializer,
77 {
78 match self {
79 SystemVersion::Semantic(version) => serializer.serialize_str(&version.to_string()),
80 SystemVersion::Opaque(string) => serializer.serialize_str(string),
81 }
82 }
83}
84
85impl FromStr for SystemVersion {
86 type Err = Infallible;
87
88 fn from_str(s: &str) -> Result<Self, Self::Err> {
89 let result = match SemanticVersion::from_str(s) {
90 Ok(version) => SystemVersion::Semantic(version),
91 Err(_) => SystemVersion::Opaque(s.trim_end().to_owned()),
92 };
93
94 Ok(result)
95 }
96}
97
98impl fmt::Display for SystemVersion {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 match self {
101 SystemVersion::Opaque(string) => f.write_str(string),
102 SystemVersion::Semantic(version) => version.fmt(f),
103 }
104 }
105}
106
107#[cfg(test)]
108#[allow(clippy::bool_assert_comparison)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_deserialize_version() {
114 let version: SystemVersion =
115 serde_json::from_str(r#""not a real version number""#).unwrap();
116 assert_eq!(version, SystemVersion::Opaque("not a real version number".to_owned()));
117 let version: SystemVersion = serde_json::from_str(r#""1.2.3""#).unwrap();
118 assert_eq!(version, SystemVersion::Semantic(SemanticVersion::from([1, 2, 3])));
119 }
120
121 #[test]
122 fn test_serialize_version() {
123 let version = SystemVersion::Opaque("not a real version number".to_owned());
124 assert_eq!(
125 serde_json::to_string(&version).unwrap(),
126 r#""not a real version number""#.to_owned()
127 );
128 let version = SystemVersion::Semantic(SemanticVersion::from([1, 3, 4, 5]));
129 assert_eq!(serde_json::to_string(&version).unwrap(), r#""1.3.4.5""#.to_owned());
130 }
131
132 #[test]
133 fn test_version_order_both_opaque() {
134 let a = SystemVersion::Opaque("version 1".to_string());
136 let b = SystemVersion::Opaque("another version".to_string());
137 assert_eq!(a < b, false);
138 assert_eq!(a > b, false);
139 assert_eq!(a >= b, false);
140 assert_eq!(a <= b, false);
141 }
142
143 #[test]
144 fn test_version_order_one_opaque() {
145 let a = SystemVersion::Opaque("opaque".to_string());
146 let b = SystemVersion::Semantic(SemanticVersion::from([1, 2, 3, 4]));
147 assert_eq!(a < b, false);
148 assert_eq!(a > b, false);
149 assert_eq!(a >= b, false);
150 assert_eq!(a <= b, false);
151 assert_eq!(b < a, false);
152 assert_eq!(b > a, false);
153 assert_eq!(b >= a, false);
154 assert_eq!(b <= a, false);
155 }
156
157 #[test]
158 fn test_version_order_both_semantic() {
159 let a = SystemVersion::Semantic(SemanticVersion::from([1, 2, 3, 4]));
160 let b = SystemVersion::Semantic(SemanticVersion::from([1, 2, 3, 5]));
161
162 assert_eq!(a < b, true);
163 assert_eq!(a <= b, true);
164 assert_eq!(a > b, false);
165 assert_eq!(a >= b, false);
166 assert_eq!(b < a, false);
167 assert_eq!(b <= a, false);
168 assert_eq!(b >= a, true);
169 assert_eq!(b > a, true);
170 }
171}