Skip to content

Commit d7fa166

Browse files
Merge pull request #1211 from andre-braga/display
uefi: Make TimeError more descriptive
2 parents bd7caae + 871c3f1 commit d7fa166

File tree

2 files changed

+86
-16
lines changed

2 files changed

+86
-16
lines changed

Diff for: uefi/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
- Added `TryFrom<&[u8]>` for `DevicePathHeader`, `DevicePathNode` and `DevicePath`.
1515
- Added `ByteConversionError`.
1616
- Re-exported `CapsuleFlags`.
17+
- One can now specify in `TimeError` what fields of `Time` are outside its valid
18+
range. `Time::is_valid` has been updated accordingly.
1719

1820
## Changed
1921
- `SystemTable::exit_boot_services` is now `unsafe`. See that method's

Diff for: uefi/src/table/runtime.rs

+84-16
Original file line numberDiff line numberDiff line change
@@ -371,19 +371,61 @@ pub struct TimeParams {
371371
pub daylight: Daylight,
372372
}
373373

374-
/// Error returned by [`Time`] methods if the input is outside the valid range.
375-
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
376-
pub struct TimeError;
374+
/// Error returned by [`Time`] methods. A bool value of `true` means
375+
/// the specified field is outside of its valid range.
376+
#[allow(missing_docs)]
377+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
378+
pub struct TimeError {
379+
pub year: bool,
380+
pub month: bool,
381+
pub day: bool,
382+
pub hour: bool,
383+
pub minute: bool,
384+
pub second: bool,
385+
pub nanosecond: bool,
386+
pub timezone: bool,
387+
pub daylight: bool,
388+
}
389+
390+
#[cfg(feature = "unstable")]
391+
impl core::error::Error for TimeError {}
377392

378393
impl Display for TimeError {
379394
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
380-
write!(f, "{self:?}")
395+
if self.year {
396+
writeln!(f, "year not within `1900..=9999`")?;
397+
}
398+
if self.month {
399+
writeln!(f, "month not within `1..=12")?;
400+
}
401+
if self.day {
402+
writeln!(f, "day not within `1..=31`")?;
403+
}
404+
if self.hour {
405+
writeln!(f, "hour not within `0..=23`")?;
406+
}
407+
if self.minute {
408+
writeln!(f, "minute not within `0..=59`")?;
409+
}
410+
if self.second {
411+
writeln!(f, "second not within `0..=59`")?;
412+
}
413+
if self.nanosecond {
414+
writeln!(f, "nanosecond not within `0..=999_999_999`")?;
415+
}
416+
if self.timezone {
417+
writeln!(
418+
f,
419+
"time_zone not `Time::UNSPECIFIED_TIMEZONE` nor within `-1440..=1440`"
420+
)?;
421+
}
422+
if self.daylight {
423+
writeln!(f, "unknown bits set for daylight")?;
424+
}
425+
Ok(())
381426
}
382427
}
383428

384-
#[cfg(feature = "unstable")]
385-
impl core::error::Error for TimeError {}
386-
387429
impl Time {
388430
/// Unspecified Timezone/local time.
389431
const UNSPECIFIED_TIMEZONE: i16 = uefi_raw::time::Time::UNSPECIFIED_TIMEZONE;
@@ -404,11 +446,8 @@ impl Time {
404446
daylight: params.daylight,
405447
pad2: 0,
406448
});
407-
if time.is_valid() {
408-
Ok(time)
409-
} else {
410-
Err(TimeError)
411-
}
449+
450+
time.is_valid().map(|_| time)
412451
}
413452

414453
/// Create an invalid `Time` with all fields set to zero. This can
@@ -422,10 +461,39 @@ impl Time {
422461
Self(uefi_raw::time::Time::invalid())
423462
}
424463

425-
/// True if all fields are within valid ranges, false otherwise.
426-
#[must_use]
427-
pub fn is_valid(&self) -> bool {
428-
self.0.is_valid()
464+
/// `Ok()` if all fields are within valid ranges, `Err(TimeError)` otherwise.
465+
pub fn is_valid(&self) -> core::result::Result<(), TimeError> {
466+
let mut err = TimeError::default();
467+
if !(1900..=9999).contains(&self.year()) {
468+
err.year = true;
469+
}
470+
if !(1..=12).contains(&self.month()) {
471+
err.month = true;
472+
}
473+
if !(1..=31).contains(&self.day()) {
474+
err.day = true;
475+
}
476+
if self.hour() > 23 {
477+
err.hour = true;
478+
}
479+
if self.minute() > 59 {
480+
err.minute = true;
481+
}
482+
if self.second() > 59 {
483+
err.second = true;
484+
}
485+
if self.nanosecond() > 999_999_999 {
486+
err.nanosecond = true;
487+
}
488+
if self.time_zone().is_some() && !((-1440..=1440).contains(&self.time_zone().unwrap())) {
489+
err.timezone = true;
490+
}
491+
// All fields are false, i.e., within their valid range.
492+
if err == TimeError::default() {
493+
Ok(())
494+
} else {
495+
Err(err)
496+
}
429497
}
430498

431499
/// Query the year.

0 commit comments

Comments
 (0)