1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use regex::Regex;
use std::error::Error;
pub struct GodotVersion {
pub major: u8,
pub minor: u8,
pub patch: u8, pub stability: String, }
pub fn parse_godot_version(version_str: &str) -> Result<GodotVersion, Box<dyn Error>> {
let regex = Regex::new("(\\d+)\\.(\\d+)(?:\\.(\\d+))?\\.(stable|beta|dev)")?;
let caps = regex.captures(version_str).ok_or("Regex capture failed")?;
let fail = || format!("Version substring could not be matched in '{version_str}'");
Ok(GodotVersion {
major: caps.get(1).ok_or_else(fail)?.as_str().parse::<u8>()?,
minor: caps.get(2).ok_or_else(fail)?.as_str().parse::<u8>()?,
patch: caps
.get(3)
.map(|m| m.as_str().parse::<u8>())
.transpose()?
.unwrap_or(0),
stability: caps.get(4).ok_or_else(fail)?.as_str().to_string(),
})
}
#[test]
fn test_godot_versions() {
let good_versions = [
("3.0.stable.official", 3, 0, 0, "stable"),
("3.0.1.stable.official", 3, 0, 1, "stable"),
("3.2.stable.official", 3, 2, 0, "stable"),
("3.37.stable.official", 3, 37, 0, "stable"),
("3.4.stable.official.206ba70f4", 3, 4, 0, "stable"),
("3.4.1.stable.official.aa1b95889", 3, 4, 1, "stable"),
("3.5.beta.custom_build.837f2c5f8", 3, 5, 0, "beta"),
("4.0.dev.custom_build.e7e9e663b", 4, 0, 0, "dev"),
];
let bad_versions = [
"4.0.unstable.custom_build.e7e9e663b", "4.0.3.custom_build.e7e9e663b", "3.stable.official.206ba70f4", ];
for (full, major, minor, patch, stability) in good_versions {
let parsed: GodotVersion = parse_godot_version(full).unwrap();
assert_eq!(parsed.major, major);
assert_eq!(parsed.minor, minor);
assert_eq!(parsed.patch, patch);
assert_eq!(parsed.stability, stability);
}
for full in bad_versions {
let parsed = parse_godot_version(full);
assert!(parsed.is_err());
}
}