| use core::fmt; |
| |
| /// A revision of the UEFI specification. |
| /// |
| /// The major revision number is incremented on major, API-incompatible changes. |
| /// |
| /// The minor revision number is incremented on minor changes, |
| /// it is stored as a two-digit binary-coded decimal. |
| /// |
| /// # Display format |
| /// |
| /// For major revision 2 and later, if the lower minor digit is zero, |
| /// the revision is formatted as "major.minor-upper". Otherwise it's |
| /// formatted as "major.minor-upper.minor-lower". This format is |
| /// described in the "EFI System Table" section of the UEFI |
| /// Specification. |
| /// |
| /// Prior to major version 2, the revision is always formatted as |
| /// "major.minor", with minor left-padded with zero if minor-upper is |
| /// zero. |
| /// |
| /// Examples: |
| /// |
| /// ``` |
| /// # use uefi_raw::table::Revision; |
| /// assert_eq!(Revision::EFI_1_02.to_string(), "1.02"); |
| /// assert_eq!(Revision::EFI_1_10.to_string(), "1.10"); |
| /// assert_eq!(Revision::EFI_2_00.to_string(), "2.0"); |
| /// assert_eq!(Revision::EFI_2_30.to_string(), "2.3"); |
| /// assert_eq!(Revision::EFI_2_31.to_string(), "2.3.1"); |
| /// assert_eq!(Revision::EFI_2_100.to_string(), "2.10"); |
| /// ``` |
| #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| #[repr(transparent)] |
| pub struct Revision(pub u32); |
| |
| // Allow missing docs, there's nothing useful to document about these |
| // constants. |
| #[allow(missing_docs)] |
| impl Revision { |
| pub const EFI_1_02: Self = Self::new(1, 2); |
| pub const EFI_1_10: Self = Self::new(1, 10); |
| pub const EFI_2_00: Self = Self::new(2, 00); |
| pub const EFI_2_10: Self = Self::new(2, 10); |
| pub const EFI_2_20: Self = Self::new(2, 20); |
| pub const EFI_2_30: Self = Self::new(2, 30); |
| pub const EFI_2_31: Self = Self::new(2, 31); |
| pub const EFI_2_40: Self = Self::new(2, 40); |
| pub const EFI_2_50: Self = Self::new(2, 50); |
| pub const EFI_2_60: Self = Self::new(2, 60); |
| pub const EFI_2_70: Self = Self::new(2, 70); |
| pub const EFI_2_80: Self = Self::new(2, 80); |
| pub const EFI_2_90: Self = Self::new(2, 90); |
| pub const EFI_2_100: Self = Self::new(2, 100); |
| } |
| |
| impl Revision { |
| /// Creates a new revision. |
| #[must_use] |
| pub const fn new(major: u16, minor: u16) -> Self { |
| let major = major as u32; |
| let minor = minor as u32; |
| let value = (major << 16) | minor; |
| Self(value) |
| } |
| |
| /// Returns the major revision. |
| #[must_use] |
| pub const fn major(self) -> u16 { |
| (self.0 >> 16) as u16 |
| } |
| |
| /// Returns the minor revision. |
| #[must_use] |
| pub const fn minor(self) -> u16 { |
| self.0 as u16 |
| } |
| } |
| |
| impl fmt::Display for Revision { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| let (major, minor) = (self.major(), self.minor()); |
| |
| if major < 2 { |
| write!(f, "{major}.{minor:02}") |
| } else { |
| let (minor, patch) = (minor / 10, minor % 10); |
| if patch == 0 { |
| write!(f, "{major}.{minor}") |
| } else { |
| write!(f, "{major}.{minor}.{patch}") |
| } |
| } |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn test_revision() { |
| let rev = Revision::EFI_2_31; |
| assert_eq!(rev.major(), 2); |
| assert_eq!(rev.minor(), 31); |
| assert_eq!(rev.0, 0x0002_001f); |
| |
| assert!(Revision::EFI_1_10 < Revision::EFI_2_00); |
| } |
| } |