use rhai::{Dynamic, EvalAltResult, Position};
use rust_sdk_common_utils::errors::RustCommonUtilsError;
use strum_macros::{AsRefStr, Display, EnumString};
pub(crate) const ERROR_MODULE_NAME: &str = "CommonUtilsErrorKind";
macro_rules! define_error_kinds {
($($variant:ident),* $(,)?) => {
#[non_exhaustive]
#[derive(Debug, Clone, Eq, PartialEq, Hash, EnumString, AsRefStr, Display)]
pub enum RhaiCommonUtilsErrorKind {
$($variant,)*
Other,
}
impl From<&RustCommonUtilsError> for RhaiCommonUtilsErrorKind {
fn from(error: &RustCommonUtilsError) -> Self {
match error {
$(RustCommonUtilsError::$variant { .. } => Self::$variant,)*
_ => Self::Other,
}
}
}
};
}
define_error_kinds! {
ParseError,
InvalidArguments,
FormatError,
}
pub fn rust_common_util_errors_to_dynamic(error: &RustCommonUtilsError) -> Dynamic {
let mut map = rhai::Map::new();
let kind: RhaiCommonUtilsErrorKind = error.into();
map.insert("kind".into(), Dynamic::from(kind));
map.insert("message".into(), Dynamic::from(format!("{error}")));
map.insert(
"source".into(),
Dynamic::from(ERROR_MODULE_NAME.to_string()),
);
Dynamic::from(map)
}
pub fn convert_to_rhai_error<T>(error: &RustCommonUtilsError) -> Result<T, Box<EvalAltResult>> {
let error_obj = rust_common_util_errors_to_dynamic(error);
Err(Box::new(EvalAltResult::ErrorRuntime(
error_obj,
Position::NONE,
)))
}
#[cfg(test)]
mod tests {
use super::*;
const EXPECTED_ERR: RhaiCommonUtilsErrorKind = RhaiCommonUtilsErrorKind::InvalidArguments;
fn get_error() -> RustCommonUtilsError {
RustCommonUtilsError::InvalidArguments {
message: "invalid arguments".to_string(),
}
}
fn get_error_kind(error: &RustCommonUtilsError) -> RhaiCommonUtilsErrorKind {
let dynamic = rust_common_util_errors_to_dynamic(error);
let map = dynamic.try_cast::<rhai::Map>().unwrap();
map.get("kind")
.unwrap()
.clone()
.cast::<RhaiCommonUtilsErrorKind>()
}
#[test]
fn test_invalid_arguments_mapping() {
let error = get_error();
assert_eq!(get_error_kind(&error), EXPECTED_ERR);
}
#[test]
fn test_successful_mapping() {
let error = get_error();
assert_eq!(get_error_kind(&error), EXPECTED_ERR);
}
#[test]
fn test_convert_to_rhai_error() {
let error = RustCommonUtilsError::InvalidArguments {
message: "test invalid arguments error".to_string(),
};
let result: Result<String, Box<EvalAltResult>> = convert_to_rhai_error(&error);
assert!(result.is_err());
if let Err(eval_error) = result {
if let EvalAltResult::ErrorRuntime(obj, _) = *eval_error {
let map = obj.try_cast::<rhai::Map>().unwrap();
assert_eq!(
map.get("message").unwrap().to_string(),
"Invalid arguments: test invalid arguments error"
);
let kind = map
.get("kind")
.unwrap()
.clone()
.cast::<RhaiCommonUtilsErrorKind>();
assert_eq!(kind, RhaiCommonUtilsErrorKind::InvalidArguments);
}
}
}
#[test]
fn test_parse_error_mapping() {
let error = RustCommonUtilsError::ParseError {
message: "parse failed".to_string(),
};
let kind = get_error_kind(&error);
assert_eq!(kind, RhaiCommonUtilsErrorKind::ParseError);
}
#[test]
fn test_format_error_mapping() {
let error = RustCommonUtilsError::FormatError {
message: "format failed".to_string(),
};
let kind = get_error_kind(&error);
assert_eq!(kind, RhaiCommonUtilsErrorKind::FormatError);
}
}