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