blob: 808208bb0732a8f6df831cceecb1573cdda0a873 [file] [log] [blame]
use super::{Error, Result};
use core::fmt::Debug;
pub use uefi_raw::Status;
/// Extension trait which provides some convenience methods for [`Status`].
pub trait StatusExt {
/// Converts this status code into a [`uefi::Result`].
///
/// If the status does not indicate success, the status representing the specific error
/// code is embedded into the `Err` variant of type [`uefi::Error`].
fn to_result(self) -> Result;
/// Converts this status code into a [`uefi::Result`] with a given `Ok` value.
///
/// If the status does not indicate success, the status representing the specific error
/// code is embedded into the `Err` variant of type [`uefi::Error`].
fn to_result_with_val<T>(self, val: impl FnOnce() -> T) -> Result<T, ()>;
/// Converts this status code into a [`uefi::Result`] with a given `Err` payload.
///
/// If the status does not indicate success, the status representing the specific error
/// code is embedded into the `Err` variant of type [`uefi::Error`].
fn to_result_with_err<ErrData: Debug>(
self,
err: impl FnOnce(Status) -> ErrData,
) -> Result<(), ErrData>;
/// Convert this status code into a result with a given `Ok` value and `Err` payload.
///
/// If the status does not indicate success, the status representing the specific error
/// code is embedded into the `Err` variant of type [`uefi::Error`].
fn to_result_with<T, ErrData: Debug>(
self,
val: impl FnOnce() -> T,
err: impl FnOnce(Status) -> ErrData,
) -> Result<T, ErrData>;
}
impl StatusExt for Status {
#[inline]
fn to_result(self) -> Result {
if self.is_success() {
Ok(())
} else {
Err(self.into())
}
}
#[inline]
fn to_result_with_val<T>(self, val: impl FnOnce() -> T) -> Result<T, ()> {
if self.is_success() {
Ok(val())
} else {
Err(self.into())
}
}
#[inline]
fn to_result_with_err<ErrData: Debug>(
self,
err: impl FnOnce(Self) -> ErrData,
) -> Result<(), ErrData> {
if self.is_success() {
Ok(())
} else {
Err(Error::new(self, err(self)))
}
}
#[inline]
fn to_result_with<T, ErrData: Debug>(
self,
val: impl FnOnce() -> T,
err: impl FnOnce(Self) -> ErrData,
) -> Result<T, ErrData> {
if self.is_success() {
Ok(val())
} else {
Err(Error::new(self, err(self)))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_status_to_result() {
assert!(Status::SUCCESS.to_result().is_ok());
assert!(Status::WARN_DELETE_FAILURE.to_result().is_err());
assert!(Status::BUFFER_TOO_SMALL.to_result().is_err());
assert_eq!(Status::SUCCESS.to_result_with_val(|| 123).unwrap(), 123);
assert!(Status::WARN_DELETE_FAILURE
.to_result_with_val(|| 123)
.is_err());
assert!(Status::BUFFER_TOO_SMALL.to_result_with_val(|| 123).is_err());
assert!(Status::SUCCESS.to_result_with_err(|_| 123).is_ok());
assert_eq!(
*Status::WARN_DELETE_FAILURE
.to_result_with_err(|_| 123)
.unwrap_err()
.data(),
123
);
assert_eq!(
*Status::BUFFER_TOO_SMALL
.to_result_with_err(|_| 123)
.unwrap_err()
.data(),
123
);
assert_eq!(
Status::SUCCESS.to_result_with(|| 123, |_| 456).unwrap(),
123
);
assert_eq!(
*Status::WARN_DELETE_FAILURE
.to_result_with(|| 123, |_| 456)
.unwrap_err()
.data(),
456
);
assert_eq!(
*Status::BUFFER_TOO_SMALL
.to_result_with(|| 123, |_| 456)
.unwrap_err()
.data(),
456
);
}
}