Skip to content

Commit 7be3135

Browse files
committed
uefi: add jiff02 feature and integrate jiff types with struct Time
1 parent c383477 commit 7be3135

9 files changed

Lines changed: 198 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ rust-version = "1.88"
2222
[workspace.dependencies]
2323
bitflags = "2.0.0"
2424
log = { version = "0.4.5", default-features = false }
25+
jiff = { version = "0.2", default-features = false }
2526
ptr_meta = { version = "0.3.0", default-features = false, features = ["derive"] }
2627
time = { version = "0.3", default-features = false }
2728
uguid = "2.2.1"

uefi/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
- Integration of `Time` with `time` crate
2323
- `TryFrom`: `time::PrimitiveDateTime <--> Time` (without timezone)
2424
- `TryFrom`: `time::OffsetDateTime <--> Time` (with timezone)
25+
- Integration of `Time` with `jiff` crate
26+
- `TryFrom`: `jiff::DateTime <--> Time` (without timezone)
27+
- `TryFrom`: `jiff::Zoned <--> Time` (with timezone)
2528

2629
## Changed
2730
- export all `text::{input, output}::*` types

uefi/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ rust-version.workspace = true
2020
# KEEP this feature list in sync with doc in uefi/lib.rs!
2121
default = [ ]
2222
alloc = []
23+
# Integration with jiff crate `>= v0.2`
24+
jiff02 = ["dep:jiff"]
2325
# Integration with time crate `>= v0.3`
2426
time03 = ["dep:time"]
2527

@@ -41,6 +43,7 @@ log-debugcon = []
4143
bitflags.workspace = true
4244
log.workspace = true
4345
ptr_meta.workspace = true
46+
jiff = { workspace = true, optional = true }
4447
time = { workspace = true, optional = true }
4548
uguid.workspace = true
4649
cfg-if = "1.0.0"

uefi/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@
142142
//! using this feature, or no allocator at all if you don't need to
143143
//! dynamically allocate any memory. Note that even without that feature,
144144
//! some code might use the internal UEFI allocator.
145+
//! - `jiff02`: Integration of [`runtime::Time`] with the `jiff` crate
146+
//! (version 0.2 and possible above). Specifically, it integrates the time
147+
//! struct with `DateTime` and `Zoned` via `TryFrom`.
145148
//! - `logger`: Logging implementation for the standard [`log`] crate
146149
//! that prints output to the UEFI console. No buffering is done; this
147150
//! is not a high-performance logger.

uefi/src/runtime/time_defs/integration_common.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub(super) enum ConversionErrorInner {
4141
/// Errors raised in the [`time`] crate.
4242
#[cfg(feature = "time03")]
4343
TimeCrateError(time::Error),
44+
/// Errors raised in the [`jiff`] crate.
45+
#[cfg(feature = "jiff02")]
46+
JiffCrateError(jiff::Error),
4447
}
4548

4649
impl Display for ConversionErrorInner {
@@ -51,6 +54,8 @@ impl Display for ConversionErrorInner {
5154
Self::UnspecifiedTimezone => write!(f, "Unspecified timezone"),
5255
#[cfg(feature = "time03")]
5356
Self::TimeCrateError(e) => write!(f, "Time crate error: {}", e),
57+
#[cfg(feature = "jiff02")]
58+
Self::JiffCrateError(e) => write!(f, "Jiff crate error: {}", e),
5459
}
5560
}
5661
}
@@ -63,6 +68,9 @@ impl Error for ConversionErrorInner {
6368
Self::UnspecifiedTimezone => None,
6469
#[cfg(feature = "time03")]
6570
Self::TimeCrateError(e) => Some(e),
71+
// None: Missing Error trait
72+
#[cfg(feature = "jiff02")]
73+
Self::JiffCrateError(_e) => None,
6674
}
6775
}
6876
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
//! Integration of the UEFI [`Time`] type with the [`jiff`] crate.
4+
5+
use super::Time;
6+
use super::integration_common::{ConversionError, ConversionErrorInner};
7+
use jiff::Zoned;
8+
use jiff::civil::DateTime;
9+
use jiff::tz::{Offset, TimeZone};
10+
use uefi::runtime::TimeParams;
11+
12+
// Timezone unaware
13+
impl TryFrom<Time> for DateTime {
14+
type Error = ConversionError;
15+
16+
fn try_from(value: Time) -> Result<Self, Self::Error> {
17+
if let Err(e) = value.is_valid() {
18+
return Err(ConversionError(ConversionErrorInner::InvalidUefiTime(e)));
19+
}
20+
21+
let datetime = Self::new(
22+
// Cannot fail as the value is valid and in range (we checked that).
23+
i16::try_from(value.0.year).unwrap(),
24+
// Cannot fail as the value is valid and in range (we checked that).
25+
i8::try_from(value.0.month).unwrap(),
26+
// Cannot fail as the value is valid and in range (we checked that).
27+
i8::try_from(value.0.day).unwrap(),
28+
// Cannot fail as the value is valid and in range (we checked that).
29+
i8::try_from(value.0.hour).unwrap(),
30+
// Cannot fail as the value is valid and in range (we checked that).
31+
i8::try_from(value.0.minute).unwrap(),
32+
// Cannot fail as the value is valid and in range (we checked that).
33+
i8::try_from(value.0.second).unwrap(),
34+
// Cannot fail as the value is valid and in range (we checked that).
35+
i32::try_from(value.0.nanosecond).unwrap(),
36+
)
37+
.map_err(|e| ConversionError(ConversionErrorInner::JiffCrateError(e)))?;
38+
39+
Ok(datetime)
40+
}
41+
}
42+
43+
// Timezone aware
44+
impl TryFrom<Time> for Zoned {
45+
type Error = ConversionError;
46+
47+
fn try_from(value: Time) -> Result<Self, Self::Error> {
48+
if let Err(e) = value.is_valid() {
49+
return Err(ConversionError(ConversionErrorInner::InvalidUefiTime(e)));
50+
}
51+
52+
if value.0.time_zone == Time::UNSPECIFIED_TIMEZONE {
53+
return Err(ConversionError(ConversionErrorInner::UnspecifiedTimezone));
54+
}
55+
56+
let datetime = DateTime::try_from(value)?;
57+
let seconds = value.0.time_zone as i32 * 60 /* seconds per minute */;
58+
let offset = Offset::from_seconds(seconds)
59+
.map_err(|e| ConversionError(ConversionErrorInner::JiffCrateError(e)))?;
60+
let timezone = TimeZone::fixed(offset);
61+
let zoned = datetime
62+
.to_zoned(timezone)
63+
.map_err(|e| ConversionError(ConversionErrorInner::JiffCrateError(e)))?;
64+
Ok(zoned)
65+
}
66+
}
67+
68+
impl TryFrom<DateTime> for Time {
69+
type Error = ConversionError;
70+
71+
fn try_from(value: DateTime) -> Result<Self, Self::Error> {
72+
let params = TimeParams {
73+
year: u16::try_from(value.year())
74+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
75+
month: u8::try_from(value.month())
76+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
77+
day: u8::try_from(value.day())
78+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
79+
hour: u8::try_from(value.hour())
80+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
81+
minute: u8::try_from(value.minute())
82+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
83+
second: u8::try_from(value.second())
84+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
85+
nanosecond: u32::try_from(value.subsec_nanosecond())
86+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
87+
time_zone: None,
88+
daylight: Default::default(),
89+
};
90+
Self::new(params).map_err(|e| ConversionError(ConversionErrorInner::InvalidUefiTime(e)))
91+
}
92+
}
93+
94+
impl TryFrom<Zoned> for Time {
95+
type Error = ConversionError;
96+
fn try_from(value: Zoned) -> Result<Self, Self::Error> {
97+
let params = TimeParams {
98+
year: u16::try_from(value.year())
99+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
100+
month: u8::try_from(value.month())
101+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
102+
day: u8::try_from(value.day())
103+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
104+
hour: u8::try_from(value.hour())
105+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
106+
minute: u8::try_from(value.minute())
107+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
108+
second: u8::try_from(value.second())
109+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
110+
nanosecond: u32::try_from(value.subsec_nanosecond())
111+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
112+
time_zone: Some(
113+
i16::try_from(value.offset().seconds() / 60 /* seconds per minute */)
114+
.map_err(|_e| ConversionError(ConversionErrorInner::InvalidComponent))?,
115+
),
116+
daylight: Default::default(),
117+
};
118+
Self::new(params).map_err(|e| ConversionError(ConversionErrorInner::InvalidUefiTime(e)))
119+
}
120+
}

uefi/src/runtime/time_defs/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ use core::fmt;
77
use core::fmt::{Debug, Display, Formatter};
88
use uefi_raw::time::Daylight;
99

10-
#[cfg(feature = "time03")]
10+
#[cfg(any(feature = "jiff02", feature = "time03"))]
1111
mod integration_common;
12+
#[cfg(feature = "jiff02")]
13+
mod integration_jiff_crate;
1214
#[cfg(feature = "time03")]
1315
mod integration_time_crate;
1416

@@ -25,7 +27,13 @@ mod integration_time_crate;
2527
/// - [`TryFrom`]: `PrimitiveDateTime` <--> [`Time`] (without timezone)
2628
/// - [`TryFrom`]: `OffsetDateTime` <--> [`Time`] (with timezone)
2729
///
30+
/// ## Integration with [`jiff`][jiff crate] crate
31+
///
32+
/// - [`TryFrom`]: `DateTime` <--> [`Time`] (without timezone)
33+
/// - [`TryFrom`]: `Zoned` <--> [`Time`] (with timezone)
34+
///
2835
/// [time crate]: https://crates.io/crates/time
36+
/// [jiff crate]: https://crates.io/crates/jiff
2937
#[derive(Copy, Clone, Eq, PartialEq)]
3038
#[repr(transparent)]
3139
pub struct Time(uefi_raw::time::Time);

xtask/src/cargo.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub enum Feature {
5656
Unstable,
5757
PanicHandler,
5858
Qemu,
59+
Jiff02,
5960
Time03,
6061

6162
// `uefi-test-runner` features.
@@ -77,6 +78,7 @@ impl Feature {
7778
Self::Unstable => "unstable",
7879
Self::PanicHandler => "panic_handler",
7980
Self::Qemu => "qemu",
81+
Self::Jiff02 => "jiff02",
8082
Self::Time03 => "time03",
8183

8284
Self::DebugSupport => "uefi-test-runner/debug_support",
@@ -119,7 +121,13 @@ impl Feature {
119121
/// - `include_unstable` - add all functionality behind the `unstable` feature
120122
/// - `runtime_features` - add all functionality that effect the runtime of Rust
121123
pub fn more_code(include_unstable: bool, runtime_features: bool) -> Vec<Self> {
122-
let mut base_features = vec![Self::Alloc, Self::LogDebugcon, Self::Logger, Self::Time03];
124+
let mut base_features = vec![
125+
Self::Alloc,
126+
Self::Jiff02,
127+
Self::LogDebugcon,
128+
Self::Logger,
129+
Self::Time03,
130+
];
123131
if include_unstable {
124132
base_features.extend([Self::Unstable])
125133
}
@@ -389,19 +397,19 @@ mod tests {
389397
fn test_comma_separated_features() {
390398
assert_eq!(
391399
Feature::comma_separated_string(&Feature::more_code(false, false)),
392-
"alloc,log-debugcon,logger,time03"
400+
"alloc,jiff02,log-debugcon,logger,time03"
393401
);
394402
assert_eq!(
395403
Feature::comma_separated_string(&Feature::more_code(false, true)),
396-
"alloc,log-debugcon,logger,time03,global_allocator"
404+
"alloc,jiff02,log-debugcon,logger,time03,global_allocator"
397405
);
398406
assert_eq!(
399407
Feature::comma_separated_string(&Feature::more_code(true, false)),
400-
"alloc,log-debugcon,logger,time03,unstable"
408+
"alloc,jiff02,log-debugcon,logger,time03,unstable"
401409
);
402410
assert_eq!(
403411
Feature::comma_separated_string(&Feature::more_code(true, true)),
404-
"alloc,log-debugcon,logger,time03,unstable,global_allocator"
412+
"alloc,jiff02,log-debugcon,logger,time03,unstable,global_allocator"
405413
);
406414
}
407415

0 commit comments

Comments
 (0)