mir_analyzer/
php_version.rs1use std::fmt;
8use std::str::FromStr;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct PhpVersion {
12 major: u8,
13 minor: u8,
14}
15
16impl PhpVersion {
17 pub const fn new(major: u8, minor: u8) -> Self {
18 Self { major, minor }
19 }
20
21 pub const fn major(self) -> u8 {
22 self.major
23 }
24
25 pub const fn minor(self) -> u8 {
26 self.minor
27 }
28}
29
30impl Default for PhpVersion {
31 fn default() -> Self {
32 Self::new(8, 2)
33 }
34}
35
36impl fmt::Display for PhpVersion {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(f, "{}.{}", self.major, self.minor)
39 }
40}
41
42#[derive(Debug, thiserror::Error)]
43#[error("invalid PHP version `{0}`: expected `MAJOR.MINOR` (e.g. `8.2`)")]
44pub struct ParsePhpVersionError(pub String);
45
46impl FromStr for PhpVersion {
47 type Err = ParsePhpVersionError;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 let mut parts = s.trim().split('.');
51 let major = parts
52 .next()
53 .and_then(|p| p.parse::<u8>().ok())
54 .ok_or_else(|| ParsePhpVersionError(s.to_string()))?;
55 let minor = parts.next().and_then(|p| p.parse::<u8>().ok()).unwrap_or(0);
56 Ok(Self::new(major, minor))
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn parses_major_minor() {
67 assert_eq!("8.2".parse::<PhpVersion>().unwrap(), PhpVersion::new(8, 2));
68 }
69
70 #[test]
71 fn parses_major_minor_patch() {
72 assert_eq!(
73 "8.3.7".parse::<PhpVersion>().unwrap(),
74 PhpVersion::new(8, 3)
75 );
76 }
77
78 #[test]
79 fn parses_major_only() {
80 assert_eq!("7".parse::<PhpVersion>().unwrap(), PhpVersion::new(7, 0));
81 }
82
83 #[test]
84 fn rejects_garbage() {
85 assert!("x.y".parse::<PhpVersion>().is_err());
86 assert!("".parse::<PhpVersion>().is_err());
87 }
88
89 #[test]
90 fn ordered_by_major_then_minor() {
91 assert!(PhpVersion::new(8, 1) < PhpVersion::new(8, 2));
92 assert!(PhpVersion::new(7, 4) < PhpVersion::new(8, 0));
93 }
94
95 #[test]
96 fn displays_as_major_dot_minor() {
97 assert_eq!(PhpVersion::new(8, 3).to_string(), "8.3");
98 }
99}