uefi_raw/table/
revision.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use core::fmt;
4
5/// A revision of the UEFI specification.
6///
7/// The major revision number is incremented on major, API-incompatible changes.
8///
9/// The minor revision number is incremented on minor changes,
10/// it is stored as a two-digit binary-coded decimal.
11///
12/// # Display format
13///
14/// For major revision 2 and later, if the lower minor digit is zero,
15/// the revision is formatted as "major.minor-upper". Otherwise it's
16/// formatted as "major.minor-upper.minor-lower". This format is
17/// described in the "EFI System Table" section of the UEFI
18/// Specification.
19///
20/// Prior to major version 2, the revision is always formatted as
21/// "major.minor", with minor left-padded with zero if minor-upper is
22/// zero.
23///
24/// Examples:
25///
26/// ```
27/// # use uefi_raw::table::Revision;
28/// assert_eq!(Revision::EFI_1_02.to_string(), "1.02");
29/// assert_eq!(Revision::EFI_1_10.to_string(), "1.10");
30/// assert_eq!(Revision::EFI_2_00.to_string(), "2.0");
31/// assert_eq!(Revision::EFI_2_30.to_string(), "2.3");
32/// assert_eq!(Revision::EFI_2_31.to_string(), "2.3.1");
33/// assert_eq!(Revision::EFI_2_100.to_string(), "2.10");
34/// ```
35#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
36#[repr(transparent)]
37pub struct Revision(pub u32);
38
39// Allow missing docs, there's nothing useful to document about these
40// constants.
41#[allow(missing_docs)]
42impl Revision {
43    pub const EFI_1_02: Self = Self::new(1, 2);
44    pub const EFI_1_10: Self = Self::new(1, 10);
45    pub const EFI_2_00: Self = Self::new(2, 00);
46    pub const EFI_2_10: Self = Self::new(2, 10);
47    pub const EFI_2_20: Self = Self::new(2, 20);
48    pub const EFI_2_30: Self = Self::new(2, 30);
49    pub const EFI_2_31: Self = Self::new(2, 31);
50    pub const EFI_2_40: Self = Self::new(2, 40);
51    pub const EFI_2_50: Self = Self::new(2, 50);
52    pub const EFI_2_60: Self = Self::new(2, 60);
53    pub const EFI_2_70: Self = Self::new(2, 70);
54    pub const EFI_2_80: Self = Self::new(2, 80);
55    pub const EFI_2_90: Self = Self::new(2, 90);
56    pub const EFI_2_100: Self = Self::new(2, 100);
57}
58
59impl Revision {
60    /// Creates a new revision.
61    #[must_use]
62    pub const fn new(major: u16, minor: u16) -> Self {
63        let major = major as u32;
64        let minor = minor as u32;
65        let value = (major << 16) | minor;
66        Self(value)
67    }
68
69    /// Returns the major revision.
70    #[must_use]
71    pub const fn major(self) -> u16 {
72        (self.0 >> 16) as u16
73    }
74
75    /// Returns the minor revision.
76    #[must_use]
77    pub const fn minor(self) -> u16 {
78        self.0 as u16
79    }
80}
81
82impl fmt::Display for Revision {
83    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        let (major, minor) = (self.major(), self.minor());
85
86        if major < 2 {
87            write!(f, "{major}.{minor:02}")
88        } else {
89            let (minor, patch) = (minor / 10, minor % 10);
90            if patch == 0 {
91                write!(f, "{major}.{minor}")
92            } else {
93                write!(f, "{major}.{minor}.{patch}")
94            }
95        }
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn test_revision() {
105        let rev = Revision::EFI_2_31;
106        assert_eq!(rev.major(), 2);
107        assert_eq!(rev.minor(), 31);
108        assert_eq!(rev.0, 0x0002_001f);
109
110        assert!(Revision::EFI_1_10 < Revision::EFI_2_00);
111    }
112}