use std::collections::BTreeMap;
use std::rc::Rc;
use harn_vm::{VmError, VmValue};
#[derive(Debug, thiserror::Error)]
pub enum HostlibError {
#[error(
"hostlib: {builtin} is not implemented yet (scaffolded contract without an implementation)"
)]
Unimplemented {
builtin: &'static str,
},
#[error("hostlib: {builtin}: missing required parameter '{param}'")]
MissingParameter {
builtin: &'static str,
param: &'static str,
},
#[error("hostlib: {builtin}: invalid parameter '{param}': {message}")]
InvalidParameter {
builtin: &'static str,
param: &'static str,
message: String,
},
#[error("hostlib: {builtin}: {message}")]
Backend {
builtin: &'static str,
message: String,
},
}
impl HostlibError {
pub fn builtin(&self) -> &'static str {
match self {
HostlibError::Unimplemented { builtin }
| HostlibError::MissingParameter { builtin, .. }
| HostlibError::InvalidParameter { builtin, .. }
| HostlibError::Backend { builtin, .. } => builtin,
}
}
}
impl From<HostlibError> for VmError {
fn from(err: HostlibError) -> VmError {
let kind = match err {
HostlibError::Unimplemented { .. } => "unimplemented",
HostlibError::MissingParameter { .. } => "missing_parameter",
HostlibError::InvalidParameter { .. } => "invalid_parameter",
HostlibError::Backend { .. } => "backend_error",
};
let builtin = err.builtin();
let message = err.to_string();
let mut dict: BTreeMap<String, VmValue> = BTreeMap::new();
dict.insert("kind".to_string(), VmValue::String(Rc::from(kind)));
dict.insert("builtin".to_string(), VmValue::String(Rc::from(builtin)));
dict.insert("message".to_string(), VmValue::String(Rc::from(message)));
VmError::Thrown(VmValue::Dict(Rc::new(dict)))
}
}