sea_core/
semantic_version.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
4pub struct SemanticVersion {
5    pub major: u32,
6    pub minor: u32,
7    pub patch: u32,
8}
9
10impl SemanticVersion {
11    pub fn new(major: u32, minor: u32, patch: u32) -> Self {
12        Self {
13            major,
14            minor,
15            patch,
16        }
17    }
18
19    pub fn parse(s: &str) -> Result<Self, String> {
20        let parts: Vec<&str> = s.split('.').collect();
21        if parts.len() != 3 {
22            return Err("Version must be in format major.minor.patch".to_string());
23        }
24
25        Ok(Self {
26            major: parts[0]
27                .parse()
28                .map_err(|_| "Invalid major version".to_string())?,
29            minor: parts[1]
30                .parse()
31                .map_err(|_| "Invalid minor version".to_string())?,
32            patch: parts[2]
33                .parse()
34                .map_err(|_| "Invalid patch version".to_string())?,
35        })
36    }
37
38    pub fn bump_major(&mut self) {
39        self.major += 1;
40        self.minor = 0;
41        self.patch = 0;
42    }
43
44    pub fn bump_minor(&mut self) {
45        self.minor += 1;
46        self.patch = 0;
47    }
48
49    pub fn bump_patch(&mut self) {
50        self.patch += 1;
51    }
52}
53
54impl std::fmt::Display for SemanticVersion {
55    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
56        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
57    }
58}
59
60impl Default for SemanticVersion {
61    fn default() -> Self {
62        Self::new(1, 0, 0)
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_semantic_version_parsing() {
72        let v = SemanticVersion::parse("1.2.3").unwrap();
73        assert_eq!(v.major, 1);
74        assert_eq!(v.minor, 2);
75        assert_eq!(v.patch, 3);
76    }
77
78    #[test]
79    fn test_semantic_version_parsing_invalid() {
80        assert!(SemanticVersion::parse("1.2").is_err());
81        assert!(SemanticVersion::parse("1.2.3.4").is_err());
82        assert!(SemanticVersion::parse("a.b.c").is_err());
83    }
84
85    #[test]
86    fn test_version_comparison() {
87        let v1 = SemanticVersion::new(1, 0, 0);
88        let v2 = SemanticVersion::new(2, 0, 0);
89        assert!(v1 < v2);
90
91        let v3 = SemanticVersion::new(1, 2, 0);
92        let v4 = SemanticVersion::new(1, 1, 0);
93        assert!(v3 > v4);
94
95        let v5 = SemanticVersion::new(1, 1, 2);
96        let v6 = SemanticVersion::new(1, 1, 1);
97        assert!(v5 > v6);
98    }
99
100    #[test]
101    fn test_version_bump_major() {
102        let mut v = SemanticVersion::new(1, 2, 3);
103        v.bump_major();
104        assert_eq!(v, SemanticVersion::new(2, 0, 0));
105    }
106
107    #[test]
108    fn test_version_bump_minor() {
109        let mut v = SemanticVersion::new(1, 2, 3);
110        v.bump_minor();
111        assert_eq!(v, SemanticVersion::new(1, 3, 0));
112    }
113
114    #[test]
115    fn test_version_bump_patch() {
116        let mut v = SemanticVersion::new(1, 2, 3);
117        v.bump_patch();
118        assert_eq!(v, SemanticVersion::new(1, 2, 4));
119    }
120
121    #[test]
122    fn test_version_display() {
123        let v = SemanticVersion::new(1, 2, 3);
124        assert_eq!(format!("{}", v), "1.2.3");
125    }
126
127    #[test]
128    fn test_version_default() {
129        let v = SemanticVersion::default();
130        assert_eq!(v, SemanticVersion::new(1, 0, 0));
131    }
132
133    #[test]
134    fn test_version_serialization() {
135        let v = SemanticVersion::new(1, 2, 3);
136        let json = serde_json::to_string(&v).unwrap();
137        let deserialized: SemanticVersion = serde_json::from_str(&json).unwrap();
138        assert_eq!(v, deserialized);
139    }
140}