[PATCH v1 10/28] rust: error: add `From` implementations for `Error`

Miguel Ojeda
2022-11-10T16:43:38Z

From: Wedson Almeida Filho <wedsonaf@gmail.com>

Add a set of `From` implementations for the `Error` kernel type.

These implementations allow to easily convert from standard Rust
error types to the usual kernel errors based on one of the `E*`
integer codes.

On top of that, the question mark Rust operator (`?`) implicitly
performs a conversion on the error value using the `From` trait
when propagating. Thus it is extra convenient to use.

For instance, a kernel function that needs to convert a `i64` into
a `i32` and to bubble up the error as a kernel error may write:

fn f(x: i64) -> Result<...> {
...
let y = i32::try_from(x)?;
...
}

which will transform the `TryFromIntError` into an `Err(EINVAL)`.

Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Nándor István Krácser <bonifaido@gmail.com>
Signed-off-by: Nándor István Krácser <bonifaido@gmail.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
[Reworded, adapted for upstream and applied latest changes]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/kernel/error.rs | 45 +++++++++++++++++++++++++++++++++++++++++++-
rust/kernel/lib.rs | 1 +
2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 861746f2422d..5b9751d7ff1d 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -4,7 +4,14 @@
//!
//! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h)

-use alloc::collections::TryReserveError;
+use alloc::{
+ alloc::{AllocError, LayoutError},
+ collections::TryReserveError,
+};
+
+use core::convert::From;
+use core::num::TryFromIntError;
+use core::str::Utf8Error;

/// Contains the C-compatible error codes.
pub mod code {
@@ -71,12 +78,48 @@ impl Error {
}
}

+impl From<AllocError> for Error {
+ fn from(_: AllocError) -> Error {
+ code::ENOMEM
+ }
+}
+
+impl From<TryFromIntError> for Error {
+ fn from(_: TryFromIntError) -> Error {
+ code::EINVAL
+ }
+}
+
+impl From<Utf8Error> for Error {
+ fn from(_: Utf8Error) -> Error {
+ code::EINVAL
+ }
+}
+
impl From<TryReserveError> for Error {
fn from(_: TryReserveError) -> Error {
code::ENOMEM
}
}

+impl From<LayoutError> for Error {
+ fn from(_: LayoutError) -> Error {
+ code::ENOMEM
+ }
+}
+
+impl From<core::fmt::Error> for Error {
+ fn from(_: core::fmt::Error) -> Error {
+ code::EINVAL
+ }
+}
+
+impl From<core::convert::Infallible> for Error {
+ fn from(e: core::convert::Infallible) -> Error {
+ match e {}
+ }
+}
+
/// A [`Result`] with an [`Error`] error type.
///
/// To be used as the return type for functions that may fail.
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index abd46261d385..ffc6626a6d29 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -12,6 +12,7 @@
//! do so first instead of bypassing this crate.

#![no_std]
+#![feature(allocator_api)]
#![feature(core_ffi_c)]

// Ensure conditional compilation based on the kernel configuration works;
--
2.38.1