diff --git a/server_fn/src/error.rs b/server_fn/src/error.rs index 13215a5b52..63d73b9005 100644 --- a/server_fn/src/error.rs +++ b/server_fn/src/error.rs @@ -200,6 +200,195 @@ impl From for ServerFnError { } } +/// Helper trait to convert from `Result>` to `Result>` +/// +/// This is meant to ease the use of the `?` operator: +/// ``` +/// use server_fn::{error::ConvertServerFnResult, ServerFnError}; +/// +/// enum Helper1Error { +/// ErrorCase1, +/// } +/// fn helper1() -> Result> { +/// Err(ServerFnError::WrappedServerError(Helper1Error::ErrorCase1)) +/// } +/// +/// enum Helper2Error { +/// ErrorCase2, +/// } +/// fn helper2() -> Result> { +/// Err(ServerFnError::WrappedServerError(Helper2Error::ErrorCase2)) +/// } +/// +/// enum FnError { +/// ErrorCase1, +/// ErrorCase2, +/// } +/// fn server_fn() -> Result> { +/// Ok(helper1().convert_custom_error()? +/// + helper2().convert_custom_error()?) +/// } +/// +/// impl From for FnError { +/// fn from(e: Helper1Error) -> Self { +/// match e { +/// Helper1Error::ErrorCase1 => Self::ErrorCase1, +/// } +/// } +/// } +/// +/// impl From for FnError { +/// fn from(e: Helper2Error) -> Self { +/// match e { +/// Helper2Error::ErrorCase2 => Self::ErrorCase2, +/// } +/// } +/// } +/// ``` +/// +/// See also [`ConvertDefaultServerFnResult`] for conversion from the default [`ServerFnError`] +/// and [`ConvertServerFnResult`] for conversion between different custom error types. +pub trait ConvertServerFnResult { + /// Converts a `Result>` into a `Result>`. + /// + /// `FromCustErr` must implement `Into`. + /// + /// See the [trait-level documentation](ConvertServerFnResult) for usage examples. + fn convert_custom_error(self) -> Result>; +} + +impl ConvertServerFnResult + for Result> +where + FromCustErr: Into, +{ + fn convert_custom_error(self) -> Result> { + self.map_err(|err| match err { + ServerFnError::::MissingArg(s) => { + ServerFnError::::MissingArg(s) + } + ServerFnError::::Args(s) => { + ServerFnError::::Args(s) + } + ServerFnError::::Serialization(s) => { + ServerFnError::::Serialization(s) + } + ServerFnError::::ServerError(s) => { + ServerFnError::::ServerError(s) + } + ServerFnError::::Response(s) => { + ServerFnError::::Response(s) + } + ServerFnError::::Registration(s) => { + ServerFnError::::Registration(s) + } + ServerFnError::::Request(s) => { + ServerFnError::::Request(s) + } + ServerFnError::::Deserialization(s) => { + ServerFnError::::Deserialization(s) + } + ServerFnError::::WrappedServerError(o) => { + ServerFnError::::WrappedServerError(o.into()) + } + }) + } +} + +/// Helper trait to convert from `Result` to `Result>` +/// +/// This is meant to ease the use of the `?` operator: +/// ``` +/// use server_fn::{error::ConvertDefaultServerFnResult, ServerFnError}; +/// +/// fn helper() -> Result { +/// Err(ServerFnError::ServerError(String::from("Server error"))) +/// } +/// +/// enum FnError { +/// TypedError, +/// } +/// fn server_fn() -> Result> { +/// Ok(helper().convert_custom_error()?) +/// } +/// ``` +/// +/// See also [`ConvertServerFnResult`] for conversion between different custom error types +/// and [`IntoServerFnResult`] for string-based conversion from any [`std::error::Error`]. +pub trait ConvertDefaultServerFnResult { + /// Converts a `Result` into a `Result>`. + /// + /// See the [trait-level documentation](ConvertDefaultServerFnResult) for usage examples. + fn convert_custom_error(self) -> Result>; +} +impl ConvertDefaultServerFnResult + for Result +{ + fn convert_custom_error(self) -> Result> { + self.map_err(|err| match err { + ServerFnError::MissingArg(s) => { + ServerFnError::::MissingArg(s) + } + ServerFnError::Args(s) => ServerFnError::::Args(s), + ServerFnError::Serialization(s) => { + ServerFnError::::Serialization(s) + } + ServerFnError::ServerError(s) => { + ServerFnError::::ServerError(s) + } + ServerFnError::Response(s) => ServerFnError::::Response(s), + ServerFnError::Registration(s) => { + ServerFnError::::Registration(s) + } + ServerFnError::Request(s) => ServerFnError::::Request(s), + ServerFnError::Deserialization(s) => { + ServerFnError::::Deserialization(s) + } + }) + } +} + +/// Helper trait to convert from `Result` to `Result>` +/// +/// This is meant to ease the use of the `?` operator: +/// ``` +/// use server_fn::{error::IntoServerFnResult, ServerFnError}; +/// +/// fn helper() -> Result { +/// "3".parse() +/// } +/// +/// enum FnError { +/// ErrorCase1, +/// } +/// fn server_fn() -> Result> { +/// Ok(helper().into_server_fn_result()?) +/// } +/// ``` +/// +/// See also [`ConvertDefaultServerFnResult`] for conversion from the default [`ServerFnError`] +/// and [`ConvertServerFnResult`] for conversion between different custom error types. +pub trait IntoServerFnResult { + /// Converts a `Result` into a `Result>`. + /// + /// Maps the error to [`ServerFnError::ServerError()`] using [`Error::to_string()`]. + /// + /// When using the default [`NoCustomError`], one can directly use [`Into`] instead. + /// + /// See the [trait-level documentation](IntoServerFnResult) for usage examples. + fn into_server_fn_result(self) -> Result>; +} + +impl IntoServerFnResult + for Result +{ + fn into_server_fn_result(self) -> Result> { + self.map_err(|err| { + ServerFnError::::ServerError(err.to_string()) + }) + } +} + impl Display for ServerFnError where CustErr: Display,