1use thiserror::Error;
2use zwasm_sys as sys;
3
4#[derive(Error, Debug)]
5#[error("ZwasmError: {0}")]
6pub struct ZwasmError(pub String);
7
8impl ZwasmError {
9 pub fn is_interrupted(&self) -> bool {
11 self.is_canceled() || self.is_timeout_exceeded()
12 }
13
14 pub fn is_canceled(&self) -> bool {
16 contains_case_insensitive(&self.0, "execution canceled")
17 || contains_case_insensitive(&self.0, "canceled")
18 }
19
20 pub fn is_timeout_exceeded(&self) -> bool {
22 contains_case_insensitive(&self.0, "execution timed out")
23 || contains_case_insensitive(&self.0, "timeout exceeded")
24 || contains_case_insensitive(&self.0, "timed out")
25 }
26}
27
28fn contains_case_insensitive(haystack: &str, needle: &str) -> bool {
29 haystack
30 .to_ascii_lowercase()
31 .contains(&needle.to_ascii_lowercase())
32}
33
34pub fn last_error() -> Option<ZwasmError> {
35 let err_ptr = unsafe { sys::zwasm_last_error_message() };
36 if err_ptr.is_null() {
37 None
38 } else {
39 let c_str = unsafe { std::ffi::CStr::from_ptr(err_ptr) };
40 let str_slice = c_str.to_str().unwrap_or("Invalid UTF-8");
41 Some(ZwasmError(str_slice.to_string()))
42 }
43}