alopex_cli/version/
mod.rs

1use std::fmt;
2
3use alopex_core::storage::format::FileVersion;
4
5pub mod compatibility;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
8pub struct Version {
9    pub major: u16,
10    pub minor: u16,
11    pub patch: u16,
12}
13
14impl Version {
15    pub const fn new(major: u16, minor: u16, patch: u16) -> Self {
16        Self {
17            major,
18            minor,
19            patch,
20        }
21    }
22
23    pub fn parse(raw: &str) -> Self {
24        let mut parts = raw.split('.');
25        let major = parse_part(parts.next());
26        let minor = parse_part(parts.next());
27        let patch = parse_part(parts.next());
28        Self {
29            major,
30            minor,
31            patch,
32        }
33    }
34}
35
36impl From<FileVersion> for Version {
37    fn from(value: FileVersion) -> Self {
38        Self::new(value.major, value.minor, value.patch)
39    }
40}
41
42impl fmt::Display for Version {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
45    }
46}
47
48pub fn cli_version() -> Version {
49    Version::parse(env!("CARGO_PKG_VERSION"))
50}
51
52pub fn supported_format_min() -> Version {
53    Version::new(0, 1, 0)
54}
55
56pub fn supported_format_max() -> Version {
57    Version::from(FileVersion::CURRENT)
58}
59
60fn parse_part(part: Option<&str>) -> u16 {
61    part.and_then(|value| {
62        let digits: String = value.chars().take_while(|c| c.is_ascii_digit()).collect();
63        if digits.is_empty() {
64            None
65        } else {
66            digits.parse::<u16>().ok()
67        }
68    })
69    .unwrap_or(0)
70}