Skip to main content

cc_lb_plugin_wire/
guest.rs

1extern crate alloc;
2
3use alloc::string::{String, ToString};
4
5pub fn run_string_export<F>(handler: F) -> i32
6where
7    F: FnOnce(String) -> Result<String, String>,
8{
9    match input_string().and_then(handler) {
10        Ok(output) => {
11            imp::set_output(output.as_bytes());
12            0
13        }
14        Err(error) => {
15            imp::set_error(error.as_bytes());
16            -1
17        }
18    }
19}
20
21fn input_string() -> Result<String, String> {
22    String::from_utf8(imp::input_bytes()).map_err(|error| error.to_string())
23}
24
25#[cfg(target_arch = "wasm32")]
26mod imp {
27    extern crate alloc;
28
29    use alloc::vec::Vec;
30
31    #[link(wasm_import_module = "extism:host/env")]
32    unsafe extern "C" {
33        fn input_length() -> u64;
34        fn input_load_u8(offset: u64) -> u8;
35        fn alloc(length: u64) -> u64;
36        fn output_set(offset: u64, length: u64);
37        fn error_set(offset: u64);
38        fn store_u8(offset: u64, data: u8);
39    }
40
41    pub(super) fn input_bytes() -> Vec<u8> {
42        let len = unsafe { input_length() } as usize;
43        let mut data = Vec::with_capacity(len);
44        for offset in 0..len {
45            data.push(unsafe { input_load_u8(offset as u64) });
46        }
47        data
48    }
49
50    pub(super) fn set_output(bytes: &[u8]) {
51        let offset = store_bytes(bytes);
52        unsafe { output_set(offset, bytes.len() as u64) };
53    }
54
55    pub(super) fn set_error(bytes: &[u8]) {
56        let offset = store_bytes(bytes);
57        unsafe { error_set(offset) };
58    }
59
60    fn store_bytes(bytes: &[u8]) -> u64 {
61        let offset = unsafe { alloc(bytes.len() as u64) };
62        for (index, byte) in bytes.iter().enumerate() {
63            unsafe { store_u8(offset + index as u64, *byte) };
64        }
65        offset
66    }
67}
68
69#[cfg(not(target_arch = "wasm32"))]
70mod imp {
71    extern crate alloc;
72
73    use alloc::{string::String, vec::Vec};
74
75    pub(super) fn input_bytes() -> Vec<u8> {
76        String::from("Extism guest input is only available on wasm32").into_bytes()
77    }
78
79    pub(super) fn set_output(_bytes: &[u8]) {}
80
81    pub(super) fn set_error(_bytes: &[u8]) {}
82}