diff --git a/README.md b/README.md index a71c041c..31ba399b 100644 --- a/README.md +++ b/README.md @@ -114,13 +114,13 @@ We recommend you to use the [thiserror crate](https://crates.io/crates/thiserror Popular error crates like Anyhow, Eyre, and Miette provide their own error types that encapsulate other errors. There is no direct transformation of those errors into `Diagnostic`, but we provide feature flags for each one of those crates to help you integrate them with your Lambda functions. -If you enable the features `anyhow`, `eyre`, or `miette` in the `lambda_runtime` dependency of your package. The error types provided by those crates can have blanket transformations into `Diagnostic` when the `lambda_runtime::IntoDiagnostic` trait is in scope. This trait exposes an `into_diagnostic` method that transforms those error types into a `Diagnostic`. This is an example that transforms an `anyhow::Error` into a `Diagnostic`: +If you enable the features `anyhow`, `eyre`, or `miette` in the `lambda_runtime` dependency of your package. The error types provided by those crates can have blanket transformations into `Diagnostic`. These features expose an `From for Diagnostic` implementation that transforms those error types into a `Diagnostic`. This is an example that transforms an `anyhow::Error` into a `Diagnostic`: ```rust -use lambda_runtime::{Diagnostic, IntoDiagnostic, LambdaEvent}; +use lambda_runtime::{Diagnostic, LambdaEvent}; async fn handler(_event: LambdaEvent) -> Result<(), Diagnostic> { - Err(anyhow::anyhow!("this is an error").into_diagnostic()) + Err(anyhow::anyhow!("this is an error").into()) } ``` diff --git a/examples/basic-error-error-crates-integration/src/main.rs b/examples/basic-error-error-crates-integration/src/main.rs index 203e65bf..f4048584 100644 --- a/examples/basic-error-error-crates-integration/src/main.rs +++ b/examples/basic-error-error-crates-integration/src/main.rs @@ -1,4 +1,4 @@ -use lambda_runtime::{run, service_fn, Diagnostic, IntoDiagnostic, Error, LambdaEvent}; +use lambda_runtime::{run, service_fn, Diagnostic, Error, LambdaEvent}; use serde::Deserialize; #[derive(Deserialize)] @@ -27,14 +27,14 @@ fn miette_error() -> miette::Result<()> { } /// Transform an anyhow::Error, eyre::Report, or miette::Report into a lambda_runtime::Diagnostic. -/// It does it by enabling the feature `anyhow`, `eyre` or `miette` in the runtime dependency, -/// and importing the `IntoDiagnostic` trait, which enables -/// the implementation of `into_diagnostic` for `anyhow::Error`, `eyre::Report`, and `miette::Report`. +/// It does it by enabling the feature `anyhow`, `eyre` or `miette` in the runtime dependency. +/// Those features enable the implementation of `From for Diagnostic` +/// for `anyhow::Error`, `eyre::Report`, and `miette::Report`. async fn function_handler(event: LambdaEvent) -> Result<(), Diagnostic> { match event.payload.error_type { - ErrorType::Anyhow => anyhow_error().map_err(|e| e.into_diagnostic()), - ErrorType::Eyre => eyre_error().map_err(|e| e.into_diagnostic()), - ErrorType::Miette => miette_error().map_err(|e| e.into_diagnostic()), + ErrorType::Anyhow => anyhow_error().map_err(|e| e.into()), + ErrorType::Eyre => eyre_error().map_err(|e| e.into()), + ErrorType::Miette => miette_error().map_err(|e| e.into()), } } diff --git a/lambda-runtime/src/diagnostic.rs b/lambda-runtime/src/diagnostic.rs index 22aaeb67..cd35535b 100644 --- a/lambda-runtime/src/diagnostic.rs +++ b/lambda-runtime/src/diagnostic.rs @@ -55,124 +55,21 @@ pub struct Diagnostic { pub error_message: String, } -/// Trait that adds an `into_diagnostic` method to several types, -/// including standard errors, and error types from several well known error crates. -/// -/// This trait is automatically implemented for some common types, -/// like boxed types that implement [`Error`][std::error::Error]. -/// If you use an error type which comes from a external crate like anyhow, eyre, or miette, -/// you can enable the features `anyhow`, `eyre` or `miette` in the `lambda_runtime` crate to automatically -/// implement `IntoDiagnostic`. -/// -/// Example: -/// ``` -/// use lambda_runtime::{Diagnostic, IntoDiagnostic, LambdaEvent}; -/// -/// #[derive(Debug)] -/// struct ErrorResponse(&'static str); -/// -/// impl IntoDiagnostic for ErrorResponse { -/// fn into_diagnostic(self) -> Diagnostic { -/// Diagnostic { -/// error_type: "MyError".into(), -/// error_message: self.0.into(), -/// } -/// } -/// } -/// -/// async fn function_handler(_event: LambdaEvent<()>) -> Result<(), Diagnostic> { -/// Err(ErrorResponse("this is an error response").into_diagnostic()) -/// } -/// ``` -pub trait IntoDiagnostic { - /// Converts external error types into [`Diagnostic`] - fn into_diagnostic(self) -> Diagnostic; -} - -impl IntoDiagnostic for DeserializeError { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), - } - } -} - -impl IntoDiagnostic for Error { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), - } - } -} - -impl IntoDiagnostic for Box { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), - } - } -} - -impl IntoDiagnostic for std::convert::Infallible { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), - } - } -} - -impl IntoDiagnostic for String { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self, - } - } -} - -impl IntoDiagnostic for &'static str { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.into(), - } - } -} - -impl IntoDiagnostic for std::io::Error { - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), - } - } -} - -impl IntoDiagnostic for Box -where - T: std::error::Error, -{ - fn into_diagnostic(self) -> Diagnostic { - Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), - } - } -} - impl From for Diagnostic { fn from(value: DeserializeError) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } impl From for Diagnostic { fn from(value: Error) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } @@ -181,66 +78,84 @@ where T: std::error::Error, { fn from(value: Box) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } impl From> for Diagnostic { fn from(value: Box) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } impl From for Diagnostic { fn from(value: std::convert::Infallible) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } impl From for Diagnostic { fn from(value: String) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } impl From<&'static str> for Diagnostic { fn from(value: &'static str) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } impl From for Diagnostic { fn from(value: std::io::Error) -> Self { - value.into_diagnostic() + Diagnostic { + error_type: type_name_of_val(&value), + error_message: value.to_string(), + } } } #[cfg(feature = "anyhow")] -impl IntoDiagnostic for anyhow::Error { - fn into_diagnostic(self) -> Diagnostic { +impl From for Diagnostic { + fn from(value: anyhow::Error) -> Diagnostic { Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), + error_type: type_name_of_val(&value), + error_message: value.to_string(), } } } #[cfg(feature = "eyre")] -impl IntoDiagnostic for eyre::Report { - fn into_diagnostic(self) -> Diagnostic { +impl From for Diagnostic { + fn from(value: eyre::Report) -> Diagnostic { Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), + error_type: type_name_of_val(&value), + error_message: value.to_string(), } } } #[cfg(feature = "miette")] -impl IntoDiagnostic for miette::Report { - fn into_diagnostic(self) -> Diagnostic { +impl From for Diagnostic { + fn from(value: miette::Report) -> Diagnostic { Diagnostic { - error_type: type_name_of_val(&self), - error_message: self.to_string(), + error_type: type_name_of_val(&value), + error_message: value.to_string(), } } } @@ -274,7 +189,7 @@ mod test { fn test_anyhow_integration() { use anyhow::Error as AnyhowError; let error: AnyhowError = anyhow::anyhow!("anyhow error"); - let diagnostic: Diagnostic = error.into_diagnostic(); + let diagnostic: Diagnostic = error.into(); assert_eq!(diagnostic.error_type, "&anyhow::Error"); assert_eq!(diagnostic.error_message, "anyhow error"); } @@ -284,7 +199,7 @@ mod test { fn test_eyre_integration() { use eyre::Report; let error: Report = eyre::eyre!("eyre error"); - let diagnostic: Diagnostic = error.into_diagnostic(); + let diagnostic: Diagnostic = error.into(); assert_eq!(diagnostic.error_type, "&eyre::Report"); assert_eq!(diagnostic.error_message, "eyre error"); } @@ -294,7 +209,7 @@ mod test { fn test_miette_integration() { use miette::Report; let error: Report = miette::miette!("miette error"); - let diagnostic: Diagnostic = error.into_diagnostic(); + let diagnostic: Diagnostic = error.into(); assert_eq!(diagnostic.error_type, "&miette::eyreish::Report"); assert_eq!(diagnostic.error_message, "miette error"); } diff --git a/lambda-runtime/src/lib.rs b/lambda-runtime/src/lib.rs index 9870455f..76d0562a 100644 --- a/lambda-runtime/src/lib.rs +++ b/lambda-runtime/src/lib.rs @@ -20,7 +20,7 @@ pub use tower::{self, service_fn, Service}; /// Diagnostic utilities to convert Rust types into Lambda Error types. pub mod diagnostic; -pub use diagnostic::{Diagnostic, IntoDiagnostic}; +pub use diagnostic::Diagnostic; mod deserializer; /// Tower middleware to be applied to runtime invocations.