use harn_vm::VmDictExt;
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,
},
#[error("{message}")]
SandboxViolation {
builtin: &'static str,
path: String,
message: String,
},
}
impl HostlibError {
pub fn builtin(&self) -> &'static str {
match self {
HostlibError::Unimplemented { builtin }
| HostlibError::MissingParameter { builtin, .. }
| HostlibError::InvalidParameter { builtin, .. }
| HostlibError::Backend { builtin, .. }
| HostlibError::SandboxViolation { 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",
HostlibError::SandboxViolation { .. } => "tool_rejected",
};
let path = match &err {
HostlibError::SandboxViolation { path, .. } => Some(path.clone()),
_ => None,
};
let builtin = err.builtin();
let message = err.to_string();
let mut dict: harn_vm::value::DictMap = harn_vm::value::DictMap::new();
dict.put_str("kind", kind);
dict.put_str("builtin", builtin);
dict.put_str("message", message);
if let Some(path) = path {
dict.put_str("path", path);
}
VmError::Thrown(VmValue::dict(dict))
}
}