1use crate::core::util::serialize::Serialize;
2use log::warn;
3use std::cmp::Ordering;
4use std::io::{Error, ErrorKind};
5
6const VERSION_SIZE: u8 = 4;
7
8pub fn read_pkg_version() -> Version {
9 let v = env!("CARGO_PKG_VERSION");
10
11 let tokens: Vec<&str> = v.split('.').collect();
12 if tokens.len() != 3 {
13 return Default::default();
14 }
15
16 let major = tokens[0].parse();
17 let minor = tokens[1].parse();
18 let patch = tokens[2].parse();
19
20 if major.is_err() || minor.is_err() || patch.is_err() {
21 return Default::default();
22 }
23
24 Version::new(major.unwrap(), minor.unwrap(), patch.unwrap())
25}
26
27#[derive(Debug, Default, Clone, Copy)]
28pub struct Version {
29 pub major: u8,
30 pub minor: u8,
31 pub patch: u16,
32}
33
34impl Version {
35 pub fn is_set(&self) -> bool {
36 !(self.major == 0 && self.minor == 0 && self.patch == 0)
37 }
38
39 pub fn new(major: u8, minor: u8, patch: u16) -> Self {
40 Version {
41 major,
42 minor,
43 patch,
44 }
45 }
46
47 pub fn is_same_minor_version(&self, version: &Version) -> bool {
61 self.is_set() && self.major == version.major && self.minor == version.minor
62 }
63}
64
65impl Serialize<Self> for Version {
66 fn serialize(&self) -> Vec<u8> {
67 let mut v = [self.major, self.minor].to_vec();
68 v.append(&mut self.patch.to_be_bytes().to_vec());
69 v
70 }
71
72 fn deserialize(buffer: &Vec<u8>) -> Result<Self, Error> {
73 if buffer.len() < VERSION_SIZE as usize {
74 warn!(
75 "buffer size : {:?} cannot be parsed as a version",
76 buffer.len()
77 );
78 return Err(Error::from(ErrorKind::InvalidData));
79 }
80 let ver = Version {
81 major: *buffer.get(0).ok_or(Error::from(ErrorKind::InvalidInput))?,
82 minor: *buffer.get(1).ok_or(Error::from(ErrorKind::InvalidInput))?,
83 patch: u16::from_be_bytes([
84 *buffer.get(2).ok_or(Error::from(ErrorKind::InvalidInput))?,
85 *buffer.get(3).ok_or(Error::from(ErrorKind::InvalidInput))?,
86 ]),
87 };
88
89 Ok(ver)
90 }
91}
92
93impl Eq for Version {}
94
95impl PartialEq<Self> for Version {
96 fn eq(&self, other: &Self) -> bool {
97 self.major == other.major && self.minor == other.minor && self.patch == other.patch
98 }
99}
100
101impl PartialOrd<Self> for Version {
102 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
103 if self.major < other.major {
104 return Some(Ordering::Less);
105 } else if self.major > other.major {
106 return Some(Ordering::Greater);
107 }
108 if self.minor < other.minor {
109 return Some(Ordering::Less);
110 } else if self.minor > other.minor {
111 return Some(Ordering::Greater);
112 }
113
114 self.patch.partial_cmp(&other.patch)
115 }
116}
117
118impl Ord for Version {
119 fn cmp(&self, other: &Self) -> Ordering {
120 self.partial_cmp(other).unwrap()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use crate::core::process::version::{Version, VERSION_SIZE};
127 use crate::core::util::serialize::Serialize;
128
129 #[test]
130 fn test_version_serialization() {
131 let version = Version {
132 major: 2,
133 minor: 45,
134 patch: 1243,
135 };
136 let buffer = version.serialize();
137 assert_eq!(buffer.len(), VERSION_SIZE as usize);
138 let version2 = Version::deserialize(&buffer)
139 .expect("can't deserialize given buffer to version object");
140
141 assert_eq!(version, version2);
142 }
143 #[test]
144 fn test_version_compare() {
145 assert!(
146 Version {
147 major: 10,
148 minor: 20,
149 patch: 30,
150 } < Version {
151 major: 10,
152 minor: 30,
153 patch: 20,
154 }
155 );
156 assert!(
157 Version {
158 major: 10,
159 minor: 20,
160 patch: 30,
161 } > Version {
162 major: 10,
163 minor: 10,
164 patch: 30,
165 }
166 );
167 assert!(
168 Version {
169 major: 10,
170 minor: 20,
171 patch: 30,
172 } < Version {
173 major: 10,
174 minor: 20,
175 patch: 40,
176 }
177 );
178
179 assert!(Version::new(0, 1, 7).is_same_minor_version(&Version::new(0, 1, 10)));
180 assert!(Version::new(0, 1, 7).is_same_minor_version(&Version::new(0, 1, 7)));
181 assert!(!Version::new(0, 1, 7).is_same_minor_version(&Version::new(0, 2, 7)));
182 assert!(!Version::new(0, 1, 7).is_same_minor_version(&Version::new(1, 1, 7)));
183 assert!(!Version::new(0, 1, 7).is_same_minor_version(&Version::new(1, 0, 7)));
184 assert!(!Version::new(0, 1, 7).is_same_minor_version(&Version::new(1, 0, 1)));
185 assert!(!Version::new(0, 0, 0).is_same_minor_version(&Version::new(1, 0, 1)));
186 assert!(!Version::new(0, 1, 7).is_same_minor_version(&Version::new(0, 0, 0)));
187 assert!(!Version::new(0, 0, 0).is_same_minor_version(&Version::new(0, 0, 0)));
188 }
189}