doris_rs/header/
version.rs1use crate::prelude::ParsingError;
2
3#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
5#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6pub struct Version {
7 pub major: u8,
9
10 pub minor: u8,
12}
13
14impl Default for Version {
15 fn default() -> Self {
17 Version::new(3, 0)
18 }
19}
20
21impl std::fmt::Display for Version {
22 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23 write!(f, "{}.{}", self.major, self.minor)
24 }
25}
26
27impl std::ops::Add<u8> for Version {
28 type Output = Version;
29 fn add(self, major: u8) -> Version {
30 Version {
31 major: self.major + major,
32 minor: self.minor,
33 }
34 }
35}
36
37impl std::ops::AddAssign<u8> for Version {
38 fn add_assign(&mut self, major: u8) {
39 self.major += major;
40 }
41}
42
43impl std::ops::Sub<u8> for Version {
44 type Output = Version;
45 fn sub(self, major: u8) -> Version {
46 if major >= self.major {
47 Version {
49 major: 1,
50 minor: self.minor,
51 }
52 } else {
53 Version {
54 major: self.major - major,
55 minor: self.minor,
56 }
57 }
58 }
59}
60
61impl std::ops::SubAssign<u8> for Version {
62 fn sub_assign(&mut self, major: u8) {
63 if major >= self.major {
64 self.major = 1;
66 } else {
67 self.major -= major;
68 }
69 }
70}
71
72impl From<Version> for (u8, u8) {
73 fn from(v: Version) -> Self {
74 (v.major, v.minor)
75 }
76}
77
78impl std::str::FromStr for Version {
79 type Err = ParsingError;
80 fn from_str(s: &str) -> Result<Self, Self::Err> {
81 let mut digits = s.split('.');
82
83 match s.contains('.') {
84 true => {
85 let major = digits.next().ok_or(ParsingError::Version)?;
86
87 let minor = digits.next().ok_or(ParsingError::Version)?;
88
89 let major = major.parse::<u8>().or(Err(ParsingError::Version))?;
90 let minor = minor.parse::<u8>().or(Err(ParsingError::Version))?;
91
92 Ok(Self { major, minor })
93 },
94 false => {
95 let major = digits.next().ok_or(ParsingError::Version)?;
96
97 let major = major.parse::<u8>().or(Err(ParsingError::Version))?;
98
99 Ok(Self { major, minor: 0 })
100 },
101 }
102 }
103}
104
105impl Version {
106 pub fn new(major: u8, minor: u8) -> Self {
108 Self { major, minor }
109 }
110}
111
112#[cfg(test)]
113mod test {
114 use super::*;
115 use std::str::FromStr;
116
117 #[test]
118 fn version() {
119 let version = Version::from_str("1");
120 assert!(version.is_ok());
121 let version = version.unwrap();
122 assert_eq!(version.major, 1);
123 assert_eq!(version.minor, 0);
124
125 let version = Version::from_str("1.2");
126 assert!(version.is_ok());
127 let version = version.unwrap();
128 assert_eq!(version.major, 1);
129 assert_eq!(version.minor, 2);
130
131 let version = Version::from_str("3.02");
132 assert!(version.is_ok());
133 let version = version.unwrap();
134 assert_eq!(version.major, 3);
135 assert_eq!(version.minor, 2);
136
137 let version = Version::from_str("a.b");
138 assert!(version.is_err());
139 }
140
141 #[test]
142 fn version_comparison() {
143 let v_a = Version::from_str("1.2").unwrap();
144 let v_b = Version::from_str("3.02").unwrap();
145 assert!(v_b > v_a);
146 assert!(v_b != v_a);
147 }
148
149 #[test]
150 fn version_arithmetics() {
151 let version = Version::new(3, 2);
152 assert_eq!(version + 1, Version::new(4, 2));
153 assert_eq!(version + 2, Version::new(5, 2));
154 assert_eq!(version - 2, Version::new(1, 2));
155 assert_eq!(version - 3, Version::new(1, 2)); let (maj, min): (u8, u8) = version.into();
158 assert_eq!(maj, 3);
159 assert_eq!(min, 2);
160 }
161}