cc_lb_plugin_wire/
guest.rs1extern 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}