Skip to main content

semver_common/models/
version.rs

1use crate::CommitMap;
2use derive_getters::Getters;
3use serde::{Deserialize, Serialize};
4
5/// Data structure that contains a version with a major, minor, and patch number as well as a map
6/// of commits that represent changes since the previous version.
7#[derive(Serialize, Deserialize, Getters)]
8pub struct Version {
9    major: u32,
10    minor: u32,
11    patch: u32,
12    changes: CommitMap,
13}
14
15impl Default for Version {
16    fn default() -> Self {
17        Self::new(0, 0, 0, CommitMap::new())
18    }
19}
20
21impl Version {
22    /// Gets the version in string form. Formatted, "v(major).(minor).(patch)"
23    pub fn get(&self) -> String {
24        format!("v{}.{}.{}", self.major, self.minor, self.patch)
25    }
26
27    /// Gets the version in short string form. Formatted, "(major).(minor).(patch)"
28    pub fn short(&self) -> String {
29        format!("{}.{}.{}", self.major, self.minor, self.patch)
30    }
31
32    /// Parse a string into the appropriate version numbers. Returns a tuple containing
33    /// the major, minor, and patch version numbers extracted from the string, if available.
34    pub fn parse(version: &str) -> Option<(u32, u32, u32)> {
35        if version.len() <= 1 {
36            return None;
37        }
38        let separated: Vec<&str> = version[1..].split(".").collect();
39        if separated.len() == 3 {
40            let major_version = separated.first()?;
41            let minor_version = separated.get(1)?;
42            let patch_version = separated.get(2)?;
43            return Some((
44                major_version.parse().ok()?,
45                minor_version.parse().ok()?,
46                patch_version.parse().ok()?,
47            ));
48        }
49        None
50    }
51
52    pub fn new(major: u32, minor: u32, patch: u32, changes: CommitMap) -> Self {
53        Version {
54            major,
55            minor,
56            patch,
57            changes,
58        }
59    }
60}
61
62#[cfg(test)]
63mod test {
64    use super::*;
65
66    #[test]
67    fn test_version_parse_valid() {
68        let parse_value = Version::parse("v1.9.2");
69        assert_eq!(parse_value, Some((1, 9, 2)));
70    }
71
72    #[test]
73    fn test_version_parse_invalid_full_len() {
74        let parse_value = Version::parse("oopasdf91.9.2ff");
75        assert_eq!(parse_value, None);
76    }
77
78    #[test]
79    fn test_version_parse_invalid_one_len() {
80        let parse_value = Version::parse("v");
81        assert_eq!(parse_value, None);
82    }
83
84    #[test]
85    fn test_version_parse_invalid_no_input() {
86        let parse_value = Version::parse("");
87        assert_eq!(parse_value, None);
88    }
89
90    #[test]
91    fn test_version_parse_invalid_no_int() {
92        let parse_value = Version::parse("vIU.AB.PE");
93        assert_eq!(parse_value, None);
94    }
95
96    #[test]
97    fn test_version_get() {
98        let (major, minor, patch) = Version::parse("v1.9.2").unwrap();
99        let changes = CommitMap::new();
100        let version = Version::new(major, minor, patch, changes);
101        assert_eq!(version.get(), "v1.9.2");
102    }
103}