feature (backend-rs, macro-rs): prittify error outputs for napi export

Co-authored-by: sup39 <dev@sup39.dev>
This commit is contained in:
naskya 2024-06-11 19:09:44 +09:00
parent 9ec9c31ab5
commit 1cc24b9c25
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
3 changed files with 96 additions and 5 deletions

View file

@ -0,0 +1,90 @@
//! Error formatter used until backtracing methods are standarized
use std::error::Error;
/// Prettifies [`Error`] message (mainly for napi export)
pub fn format_error(mut error: &dyn Error) -> String {
let mut to_return = String::new();
to_return.push_str(&format!(
concat!(" raw: {0:?}", "\n", " message: {0}"),
error,
));
while let Some(source) = error.source() {
to_return.push('\n');
to_return.push_str(&format!("caused by: {}", source));
error = source;
}
to_return
}
#[cfg(test)]
mod unit_test {
use pretty_assertions::assert_eq;
#[test]
fn format_error() {
#[derive(thiserror::Error, Debug)]
#[error("inner error 1")]
struct InnerError1;
#[derive(thiserror::Error, Debug)]
#[error("unexpected string '{0}'")]
struct InnerError2(String);
#[derive(thiserror::Error, Debug)]
enum ErrorVariants {
#[error("error 1 occured")]
Error1(#[from] InnerError1),
#[error("error 2 occured")]
Error2(#[from] InnerError2),
}
fn causes_inner_error_1() -> Result<(), InnerError1> {
Err(InnerError1)
}
fn causes_inner_error_2() -> Result<(), InnerError2> {
Err(InnerError2("foo".to_string()))
}
fn causes_error_1() -> Result<(), ErrorVariants> {
causes_inner_error_1()?;
Ok(())
}
fn causes_error_2() -> Result<(), ErrorVariants> {
causes_inner_error_2()?;
Ok(())
}
let error_1 = causes_error_1().unwrap_err();
let error_2 = causes_error_2().unwrap_err();
let error_message_1 = super::format_error(&error_1);
let error_message_2 = super::format_error(&error_2);
// We can't assume consistency in `Debug` output, so the output texts
// may need to be updated in the future, and we shouldn't make this kind
// of assumption in the actual program.
let expected_message_1 = "
raw: Error1(InnerError1)
message: error 1 occured
caused by: inner error 1
";
let expected_message_2 = r#"
raw: Error2(InnerError2("foo"))
message: error 2 occured
caused by: unexpected string 'foo'
"#;
assert_eq!(
error_message_1,
expected_message_1[1..expected_message_1.len() - 1]
);
assert_eq!(
error_message_2,
expected_message_2[1..expected_message_2.len() - 1]
);
}
}

View file

@ -1,5 +1,6 @@
//! Basic utilities such as ID generator and HTTP client //! Basic utilities such as ID generator and HTTP client
pub mod error_chain;
pub mod http_client; pub mod http_client;
pub mod id; pub mod id;
pub mod random; pub mod random;

View file

@ -212,7 +212,7 @@ pub fn ts_export(
/// ``` /// ```
/// ///
/// ## Function with `Result<T, E>` return type /// ## Function with `Result<T, E>` return type
/// ``` /// ```ignore
/// #[derive(thiserror::Error, Debug)] /// #[derive(thiserror::Error, Debug)]
/// pub enum IntegerDivisionError { /// pub enum IntegerDivisionError {
/// #[error("Divided by zero")] /// #[error("Divided by zero")]
@ -233,7 +233,7 @@ pub fn ts_export(
/// } /// }
/// ``` /// ```
/// generates /// generates
/// ``` /// ```ignore
/// # #[derive(thiserror::Error, Debug)] /// # #[derive(thiserror::Error, Debug)]
/// # pub enum IntegerDivisionError { /// # pub enum IntegerDivisionError {
/// # #[error("Divided by zero")] /// # #[error("Divided by zero")]
@ -252,7 +252,7 @@ pub fn ts_export(
/// # } /// # }
/// #[napi_derive::napi(js_name = "integerDivide",)] /// #[napi_derive::napi(js_name = "integerDivide",)]
/// pub fn integer_divide_napi(dividend: i64, divisor: i64) -> napi::Result<i64> { /// pub fn integer_divide_napi(dividend: i64, divisor: i64) -> napi::Result<i64> {
/// integer_divide(dividend, divisor).map_err(|err| napi::Error::from_reason(err.to_string())) /// integer_divide(dividend, divisor).map_err(|err| napi::Error::from_reason(crate::util::error_chain::format_error(&err)))
/// } /// }
/// ``` /// ```
#[proc_macro_attribute] #[proc_macro_attribute]
@ -329,7 +329,7 @@ fn napi_impl(macro_attr: TokenStream, item: TokenStream) -> TokenStream {
}; };
// add modifier to function call result // add modifier to function call result
function_call_modifiers.push(quote! { function_call_modifiers.push(quote! {
.map_err(|err| napi::Error::from_reason(err.to_string())) .map_err(|err| napi::Error::from_reason(crate::util::error_chain::format_error(&err)))
}); });
} }
}; };
@ -539,7 +539,7 @@ mod tests {
divisor: i64, divisor: i64,
) -> napi::Result<i64> { ) -> napi::Result<i64> {
integer_divide(dividend, divisor) integer_divide(dividend, divisor)
.map_err(|err| napi::Error::from_reason(err.to_string())) .map_err(|err| napi::Error::from_reason(crate::util::error_chain::format_error(&err)))
} }
} }
); );