adapter_extism/
lib.rs

1use adapter::{Adapter, AdapterInput, AdapterOutput};
2
3use extism::{FromBytes, Manifest, Plugin, ToBytes, Wasm};
4
5pub struct ExtismAdapter(Plugin);
6
7impl ExtismAdapter {
8    pub fn new(plugin: Plugin) -> Self {
9        Self(plugin)
10    }
11
12    pub fn from_url(url: &str) -> Result<Self, extism::Error> {
13        let url = Wasm::url(url);
14        let manifest = Manifest::new([url]);
15        let plugin = Plugin::new(manifest, [], true)?;
16        Ok(Self(plugin))
17    }
18}
19
20impl<'b, Input, Output> Adapter<'b, Input, Output> for ExtismAdapter
21where
22    Input: ToBytes<'b>,
23    Output: FromBytes<'b>,
24{
25    type Error = extism::Error;
26    type Identifier = &'b str;
27
28    fn call(
29        &'b mut self,
30        identifier: Self::Identifier,
31        input: Input,
32    ) -> Result<Output, Self::Error> {
33        self.0.call::<Input, Output>(identifier, input)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn it_has_the_same_output_as_extism() {
43        let uri = "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm";
44
45        let url = Wasm::url(uri);
46        let manifest = Manifest::new([url]);
47        let mut plugin = Plugin::new(manifest, [], true).unwrap();
48
49        let mut adapter = ExtismAdapter::from_url(uri).unwrap();
50
51        let identifier = "count_vowels";
52        let input = "Hello, world!";
53
54        let ours: &str = adapter.call(identifier, input).unwrap();
55
56        let theirs = plugin.call::<&str, &str>(identifier, input).unwrap();
57
58        assert_eq!(ours, theirs);
59    }
60
61    #[test]
62    fn it_can_do_multiple_calls() {
63        let uri = "https://github.com/extism/plugins/releases/latest/download/count_vowels.wasm";
64
65        let mut adapter = ExtismAdapter::from_url(uri).unwrap();
66
67        let identifier = "count_vowels";
68        let input = "Hello, world!";
69
70        let first: &str = adapter.call(identifier, input).unwrap();
71        let first = first.to_owned();
72        let second: &str = adapter.call(identifier, input).unwrap();
73        let second = second.to_owned();
74
75        assert_ne!(first, second);
76
77        assert_eq!(first, r#"{"count":3,"total":3,"vowels":"aeiouAEIOU"}"#);
78        assert_eq!(second, r#"{"count":3,"total":6,"vowels":"aeiouAEIOU"}"#);
79    }
80}