1use anyhow::Result;
2use hash_map_id::HashMapId;
3use lunatic_common_api::{get_memory, IntoTrap};
4use wasmtime::{Caller, Linker};
5
6pub type ErrorResource = HashMapId<anyhow::Error>;
7
8pub trait ErrorCtx {
9 fn error_resources(&self) -> &ErrorResource;
10 fn error_resources_mut(&mut self) -> &mut ErrorResource;
11}
12
13pub fn register<T: ErrorCtx + 'static>(linker: &mut Linker<T>) -> Result<()> {
15 linker.func_wrap("lunatic::error", "string_size", string_size)?;
16 linker.func_wrap("lunatic::error", "to_string", to_string)?;
17 linker.func_wrap("lunatic::error", "drop", drop)?;
18 Ok(())
19}
20
21fn string_size<T: ErrorCtx>(caller: Caller<T>, error_id: u64) -> Result<u32> {
26 let error = caller
27 .data()
28 .error_resources()
29 .get(error_id)
30 .or_trap("lunatic::error::string_size")?;
31 Ok(error.to_string().len() as u32)
32}
33
34fn to_string<T: ErrorCtx>(mut caller: Caller<T>, error_id: u64, error_str_ptr: u32) -> Result<()> {
41 let error = caller
42 .data()
43 .error_resources()
44 .get(error_id)
45 .or_trap("lunatic::error::string_size")?;
46 let error_str = error.to_string();
47 let memory = get_memory(&mut caller)?;
48 memory
49 .write(&mut caller, error_str_ptr as usize, error_str.as_ref())
50 .or_trap("lunatic::error::string_size")?;
51 Ok(())
52}
53
54fn drop<T: ErrorCtx>(mut caller: Caller<T>, error_id: u64) -> Result<()> {
59 caller
60 .data_mut()
61 .error_resources_mut()
62 .remove(error_id)
63 .or_trap("lunatic::error::drop")?;
64 Ok(())
65}