1use anyhow::{Result, bail};
6use regex::Regex;
7use semver::Version;
8
9use crate::log_trace;
10
11pub fn semver_parse(str: &str) -> Result<Version> {
14 let full: Regex = Regex::new(r"^\d+\.\d+\.\d+$")?;
15 let missing_patch: Regex = Regex::new(r"^\d+\.\d+$")?;
16 let full_with_pre = Regex::new(r"^(\d+\.\d+\.\d+)\-(.*)")?;
17 let missing_patch_with_pre = Regex::new(r"^(\d+\.\d+)\-(.*)")?;
18
19 if full.is_match(str) {
20 let cap = full.captures(str).unwrap();
21 let result = cap[0].to_string();
22
23 log_trace!("FULL: {}", result);
24
25 if result.is_empty() {
26 bail!(
27 "[utils][semver_parse] Failed to capture X.X.X regex from [{}]!",
28 str
29 )
30 } else {
31 Ok(Version::parse(&result)?)
32 }
33 } else if missing_patch.is_match(str) {
34 let cap = missing_patch.captures(str).unwrap();
35 let result = cap[0].to_string();
36
37 log_trace!("MISSING: {}", result);
38
39 if result.is_empty() {
40 bail!(
41 "[utils][semver_parse] Failed to capture X.X regex from [{}]!",
42 str
43 )
44 } else {
45 Ok(Version::parse(&format!("{result}.0"))?)
46 }
47 } else if full_with_pre.is_match(str) {
48 let cap = full_with_pre.captures(str).unwrap();
49 let result = cap[0].to_string();
50
51 log_trace!("full_with_pre: {}", result);
52
53 if result.is_empty() {
54 bail!(
55 "[utils][semver_parse] Failed to capture X.X.X-PRE regex from [{}]!",
56 str
57 )
58 } else {
59 Ok(Version::parse(&result)?)
60 }
61 } else if missing_patch_with_pre.is_match(str) {
62 let cap = missing_patch_with_pre.captures(str).unwrap();
63 let result = cap[1].to_string();
64 let pre = cap[2].to_string();
65
66 log_trace!("missing_patch_with_pre: {}", result);
67
68 if result.is_empty() {
69 bail!(
70 "[utils][semver_parse] Failed to capture X.X-PRE regex from [{}]!",
71 str
72 )
73 } else {
74 Ok(Version::parse(&format!("{result}.0-{pre}"))?)
75 }
76 } else {
77 bail!(
78 "[utils][semver_parse] Failed to capture any vesion regex from [{}]!",
79 str
80 )
81 }
82}
83
84pub fn semver_parse_or_default(str: &str) -> Version {
88 semver_parse(str).unwrap_or(Version::new(0, 0, 0))
89}
90
91pub fn semver_parse_regex(str: &str, pattern: &str, delimiter: &str) -> Result<Version> {
95 let re: Regex = Regex::new(pattern)?;
96
97 if re.is_match(str) {
98 let cap = re.captures(str).unwrap();
99
100 if cap.len() != 2 {
101 bail!(
102 "[utils][semver_parse_regex] Failed to capture any version group from [{}]!",
103 str
104 )
105 }
106
107 let result = cap[1].to_string();
108
109 log_trace!("version capture from str: {}", result);
110
111 let fix_delimiters = result.replace(delimiter, ".");
112
113 semver_parse(&fix_delimiters)
114 } else {
115 bail!(
116 "[utils][semver_parse_regex] Failed to capture any vesion regex from [{}]!",
117 str
118 )
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use semver::{Prerelease, Version};
125
126 use super::{semver_parse, semver_parse_regex};
127
128 #[test]
129 fn semver_parse_test() {
130 let version = "0.9.0";
131 assert_eq!(semver_parse(version).unwrap(), Version::new(0, 9, 0));
132
133 let version = "0.9";
134 assert_eq!(semver_parse(version).unwrap(), Version::new(0, 9, 0));
135
136 let version = "0.9.2-1e341234";
137 let mut expected = Version::new(0, 9, 2);
138 expected.pre = Prerelease::new("1e341234").unwrap();
139 assert_eq!(semver_parse(version).unwrap(), expected);
140
141 let version = "0.9-1-e341234";
142 let mut expected = Version::new(0, 9, 0);
143 expected.pre = Prerelease::new("1-e341234").unwrap();
144 assert_eq!(semver_parse(version).unwrap(), expected);
145
146 let version = "0.9-2";
147 let mut expected = Version::new(0, 9, 0);
148 expected.pre = Prerelease::new("2").unwrap();
149 assert_eq!(semver_parse(version).unwrap(), expected);
150 }
151
152 #[test]
153 fn semver_parse_regex_test() {
154 let input = "btsys_intbrd_boot_config_v_0_9.hex";
155
156 let pattern = "btsys_intbrd_boot_config_v_(.*).hex";
157
158 let expected_version = Version::new(0, 9, 0);
159
160 assert_eq!(
161 semver_parse_regex(&input, &pattern, "_").unwrap(),
162 expected_version
163 );
164 }
165}