chrome_for_testing/api/
version.rs1use serde::de::{self, Visitor};
2use serde::{Deserialize, Deserializer};
3use std::cmp::PartialOrd;
4use std::fmt::{Display, Formatter};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct Version {
8 pub major: u32,
9 pub minor: u32,
10 pub patch: u32,
11 pub build: u32,
12}
13
14impl Display for Version {
15 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
16 f.write_fmt(format_args!(
17 "{}.{}.{}.{}",
18 self.major, self.minor, self.patch, self.build
19 ))
20 }
21}
22
23impl PartialOrd for Version {
24 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
25 if self.major != other.major {
26 return self.major.partial_cmp(&other.major);
27 }
28 if self.minor != other.minor {
29 return self.minor.partial_cmp(&other.minor);
30 }
31 if self.patch != other.patch {
32 return self.patch.partial_cmp(&other.patch);
33 }
34 if self.build != other.build {
35 return self.build.partial_cmp(&other.build);
36 }
37 Some(std::cmp::Ordering::Equal)
38 }
39
40 fn lt(&self, other: &Self) -> bool {
41 self.partial_cmp(other) == Some(std::cmp::Ordering::Less)
42 }
43
44 fn le(&self, other: &Self) -> bool {
45 self.partial_cmp(other) != Some(std::cmp::Ordering::Greater)
46 }
47
48 fn gt(&self, other: &Self) -> bool {
49 self.partial_cmp(other) == Some(std::cmp::Ordering::Greater)
50 }
51
52 fn ge(&self, other: &Self) -> bool {
53 self.partial_cmp(other) != Some(std::cmp::Ordering::Less)
54 }
55}
56
57impl<'de> Deserialize<'de> for Version {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: Deserializer<'de>,
62 {
63 struct VersionVisitor;
64
65 impl Visitor<'_> for VersionVisitor {
66 type Value = Version;
67
68 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
69 formatter.write_str("a version string in dot format")
70 }
71
72 fn visit_str<E>(self, value: &str) -> Result<Version, E>
73 where
74 E: de::Error,
75 {
76 let parts: Vec<&str> = value.split('.').collect();
77
78 if parts.len() == 4 {
79 let major: Result<u32, E> = parts[0].parse().map_err(de::Error::custom);
80 let minor: Result<u32, E> = parts[1].parse().map_err(de::Error::custom);
81 let patch: Result<u32, E> = parts[2].parse().map_err(de::Error::custom);
82 let build: Result<u32, E> = parts[3].parse().map_err(de::Error::custom);
83
84 Ok(Version {
85 major: major?,
86 minor: minor?,
87 patch: patch?,
88 build: build?,
89 })
90 } else {
91 Err(de::Error::custom("Invalid version string format"))
92 }
93 }
94 }
95
96 deserializer.deserialize_str(VersionVisitor)
97 }
98}