tidy/features/
version.rs
1use std::fmt;
2use std::num::ParseIntError;
3use std::str::FromStr;
4
5#[cfg(test)]
6mod tests;
7
8pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
11#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
12pub enum Version {
13 Explicit { parts: [u32; 3] },
14 CurrentPlaceholder,
15}
16
17impl fmt::Display for Version {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 Version::Explicit { parts } => {
21 f.pad(&format!("{}.{}.{}", parts[0], parts[1], parts[2]))
22 }
23 Version::CurrentPlaceholder => f.pad(&format!("CURRENT")),
24 }
25 }
26}
27
28#[derive(Debug, PartialEq, Eq)]
29pub enum ParseVersionError {
30 ParseIntError(ParseIntError),
31 WrongNumberOfParts,
32}
33
34impl From<ParseIntError> for ParseVersionError {
35 fn from(err: ParseIntError) -> Self {
36 ParseVersionError::ParseIntError(err)
37 }
38}
39
40impl FromStr for Version {
41 type Err = ParseVersionError;
42
43 fn from_str(s: &str) -> Result<Self, Self::Err> {
44 if s == VERSION_PLACEHOLDER {
45 return Ok(Version::CurrentPlaceholder);
46 }
47 let mut iter = s.split('.').map(|part| Ok(part.parse()?));
48
49 let mut part = || iter.next().unwrap_or(Err(ParseVersionError::WrongNumberOfParts));
50
51 let parts = [part()?, part()?, part()?];
52
53 if iter.next().is_some() {
54 return Err(ParseVersionError::WrongNumberOfParts);
56 }
57
58 Ok(Version::Explicit { parts })
59 }
60}