libc_abi_tools/
version.rs1use std::{fmt, str::FromStr};
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
7pub struct Version {
11 pub major: u32,
13 pub minor: u32,
15 pub patch: u32,
17}
18
19impl Version {
20 pub fn validate_release(self) -> Result<Self, String> {
26 if self.major != 2 || self.minor < 17 || self.patch != 0 {
27 return Err(
28 "expected a glibc 2.x release starting at 2.17, without a patch component".into(),
29 );
30 }
31 Ok(self)
32 }
33}
34
35impl FromStr for Version {
36 type Err = String;
37
38 fn from_str(text: &str) -> Result<Self, String> {
39 let parts: Vec<_> = text.split('.').collect();
40 if !(2..=3).contains(&parts.len()) {
41 return Err(format!("invalid numeric version {text:?}"));
42 }
43 let number = |s: &str| -> Result<u32, String> {
44 if s.is_empty() || !s.bytes().all(|b| b.is_ascii_digit()) {
45 return Err(format!("invalid numeric version {text:?}"));
46 }
47 s.parse()
48 .map_err(|_| format!("version component too large: {text:?}"))
49 };
50 Ok(Self {
51 major: number(parts[0])?,
52 minor: number(parts[1])?,
53 patch: if parts.len() == 3 {
54 number(parts[2])?
55 } else {
56 0
57 },
58 })
59 }
60}
61
62impl fmt::Display for Version {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "{}.{}", self.major, self.minor)?;
65 if self.patch != 0 {
66 write!(f, ".{}", self.patch)?;
67 }
68 Ok(())
69 }
70}