Skip to content

Commit b6463a3

Browse files
committed
Implements core::error::Error on error types
1 parent fa5dac4 commit b6463a3

8 files changed

+53
-55
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ rust-version = "1.81"
99

1010
[dependencies]
1111
bitflags = "2.4"
12+
thiserror = { version = "2.0.9", default-features = false }
1213
zfi-macros = { version = "0.1", path = "macros" }
1314

1415
[dev-dependencies]

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ Keep in mind that you need to put everything your test needed in the same functi
205205
- `Image::current()` was replaced with `zfi::current_image()`.
206206
- All getters on `SystemTable` no longer return a static lifetime.
207207
- `EfiStr` and `EfiString` to longer implement `Display`. Use `EfiStr::display()` instead.
208+
- `Display` implementation of `DebugFileError`, `FileCreateError` and `FileSetLenError` no longer print the nested error. Use `core::error::Error::source()` to obtains the inner error instead.
209+
- `Path` no longer implement `Display`. Use `Path::display()` instead.
210+
- `PathNode` no longer implement `Display`. Currently no alternative is provided yet. Please create the issue if you want this feature so I can prioritize it.
208211

209212
## License
210213

src/debug.rs

+11-18
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use crate::{
55
use alloc::borrow::ToOwned;
66
use alloc::boxed::Box;
77
use core::cell::RefCell;
8-
use core::fmt::{Display, Formatter, Write};
8+
use core::fmt::Write;
9+
use thiserror::Error;
910

1011
/// Prints to the debug log, with a newline.
1112
///
@@ -87,25 +88,17 @@ impl Write for DebugFile {
8788
}
8889

8990
/// Represents an error when [`DebugFile`] constructing is failed.
90-
#[derive(Debug)]
91+
#[derive(Debug, Error)]
9192
pub enum DebugFileError {
93+
#[error("the location of the current image is not supported")]
9294
UnsupportedImageLocation,
93-
OpenRootFailed(&'static Path, Status),
95+
96+
#[error("cannot open the root directory of {}", .0.display())]
97+
OpenRootFailed(&'static Path, #[source] Status),
98+
99+
#[error("file extension contains unsupported character")]
94100
UnsupportedExtension,
95-
CreateFileFailed(EfiString, FileCreateError),
96-
}
97101

98-
impl Display for DebugFileError {
99-
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
100-
match self {
101-
Self::UnsupportedImageLocation => {
102-
f.write_str("the location of the current image is not supported")
103-
}
104-
Self::OpenRootFailed(p, e) => write!(f, "cannot open the root directory of {p} -> {e}"),
105-
Self::UnsupportedExtension => {
106-
f.write_str("file extension contains unsupported character")
107-
}
108-
Self::CreateFileFailed(p, e) => write!(f, "cannot create {p} -> {e}"),
109-
}
110-
}
102+
#[error("cannot create {}", .0.display())]
103+
CreateFileFailed(EfiString, #[source] FileCreateError),
111104
}

src/filesystem.rs

+12-23
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use alloc::alloc::{alloc, dealloc, handle_alloc_error};
33
use alloc::boxed::Box;
44
use bitflags::bitflags;
55
use core::alloc::Layout;
6-
use core::fmt::{Display, Formatter};
76
use core::mem::zeroed;
87
use core::ptr::null_mut;
8+
use thiserror::Error;
99

1010
/// Represents an `EFI_SIMPLE_FILE_SYSTEM_PROTOCOL`.
1111
#[repr(C)]
@@ -364,35 +364,24 @@ impl FileInfo {
364364
}
365365

366366
/// Represents an error when [`File::create()`] is failed.
367-
#[derive(Debug)]
367+
#[derive(Debug, Error)]
368368
pub enum FileCreateError {
369+
#[error(transparent)]
369370
CreateFailed(Status),
370-
TruncateFailed(FileSetLenError),
371-
}
372371

373-
impl Display for FileCreateError {
374-
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
375-
match self {
376-
Self::CreateFailed(e) => e.fmt(f),
377-
Self::TruncateFailed(e) => write!(f, "cannot truncate the file -> {e}"),
378-
}
379-
}
372+
#[error("cannot truncate the file")]
373+
TruncateFailed(#[source] FileSetLenError),
380374
}
381375

382376
/// Represents an error when [`File::set_len()`] is failed.
383-
#[derive(Debug)]
377+
#[derive(Debug, Error)]
384378
pub enum FileSetLenError {
385-
GetInfoFailed(Status),
379+
#[error("cannot get the current info")]
380+
GetInfoFailed(#[source] Status),
381+
382+
#[error("file is a directory")]
386383
FileIsDirectory,
387-
SetInfoFailed(Status),
388-
}
389384

390-
impl Display for FileSetLenError {
391-
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
392-
match self {
393-
Self::GetInfoFailed(e) => write!(f, "cannot get the current info -> {e}"),
394-
Self::FileIsDirectory => f.write_str("file is a directory"),
395-
Self::SetInfoFailed(e) => write!(f, "cannot set file info -> {e}"),
396-
}
397-
}
385+
#[error("cannot set file info")]
386+
SetInfoFailed(#[source] Status),
398387
}

src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ pub unsafe fn init(
7272

7373
// Check EFI version.
7474
if st.hdr().revision() < TableRevision::new(1, 1) {
75-
panic!("UEFI version is too old to run {}", im.proto().file_path());
75+
panic!(
76+
"UEFI version is too old to run {}",
77+
im.proto().file_path().display()
78+
);
7679
}
7780

7881
// Initialize debug log.

src/path.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::EfiStr;
22
use alloc::borrow::{Cow, ToOwned};
33
use core::borrow::Borrow;
4-
use core::fmt::{Display, Formatter};
4+
use core::fmt::Formatter;
55
use core::ops::Deref;
66
use core::ptr::read_unaligned;
77
use core::slice::from_raw_parts;
@@ -63,6 +63,10 @@ impl Path {
6363
pub const fn as_bytes(&self) -> &[u8] {
6464
&self.0
6565
}
66+
67+
pub const fn display(&self) -> impl core::fmt::Display + '_ {
68+
Display(self)
69+
}
6670
}
6771

6872
impl PartialEq<PathBuf> for Path {
@@ -88,13 +92,19 @@ impl<'a> IntoIterator for &'a Path {
8892
}
8993
}
9094

91-
impl Display for Path {
95+
/// Provides [`core::fmt::Display`] implementation to print [`Path`].
96+
struct Display<'a>(&'a Path);
97+
98+
impl<'a> core::fmt::Display for Display<'a> {
9299
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93-
for (i, n) in self.into_iter().enumerate() {
100+
for (i, n) in self.0.into_iter().enumerate() {
94101
if i != 0 {
95102
f.write_str("/")?;
96103
}
97-
n.read().fmt(f)?;
104+
105+
match n.read() {
106+
PathNode::MediaFilePath(v) => write!(f, "{}", v.display())?,
107+
}
98108
}
99109

100110
Ok(())
@@ -164,14 +174,6 @@ pub enum PathNode<'a> {
164174
MediaFilePath(&'a EfiStr),
165175
}
166176

167-
impl Display for PathNode<'_> {
168-
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
169-
match self {
170-
PathNode::MediaFilePath(p) => p.fmt(f),
171-
}
172-
}
173-
}
174-
175177
/// An iterator over device path nodes.
176178
pub struct PathNodes<'a>(&'a [u8]);
177179

src/status.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::error::Error;
12
use core::fmt::{Display, Formatter};
23

34
/// Represents an `EFI_STATUS`.
@@ -35,6 +36,8 @@ impl Status {
3536
}
3637
}
3738

39+
impl Error for Status {}
40+
3841
impl Display for Status {
3942
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
4043
match *self {

src/string.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use core::mem::transmute;
66
use core::ops::Deref;
77
use core::slice::{from_raw_parts, IterMut};
88
use core::str::FromStr;
9+
use thiserror::Error;
910

1011
/// A borrowed EFI string. The string is always have NUL at the end.
1112
///
@@ -212,8 +213,11 @@ impl PartialEq<u8> for EfiChar {
212213
}
213214

214215
/// Represents an error when an [`EfiString`] cnostruction is failed.
215-
#[derive(Debug)]
216+
#[derive(Debug, Error)]
216217
pub enum EfiStringError {
218+
#[error("the value contains NUL character")]
217219
HasNul(usize),
220+
221+
#[error("the value contains character outside Basic Multilingual Plane")]
218222
UnsupportedChar(usize, char),
219223
}

0 commit comments

Comments
 (0)