swc_plugin_runner/
plugin_module_bytes.rs

1use anyhow::Error;
2use serde::{Deserialize, Serialize};
3use wasmer::{Module, Store};
4
5use crate::wasix_runtime::new_store;
6
7// A trait abstracts plugin's wasm compilation and instantiation.
8// Depends on the caller, this could be a simple clone from existing module, or
9// load from file system cache.
10pub trait PluginModuleBytes {
11    // Returns a name to the module, typically either path to the plugin or its
12    // package name.
13    fn get_module_name(&self) -> &str;
14    // Returns a compiled wasmer::Module for the plugin module.
15    fn compile_module(&self) -> Result<(Store, Module), Error>;
16}
17
18/// A struct for the plugin contains raw bytes can be compiled into Wasm Module.
19#[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialEq)]
20pub struct RawPluginModuleBytes {
21    plugin_name: String,
22    bytes: Vec<u8>,
23}
24
25impl PluginModuleBytes for RawPluginModuleBytes {
26    fn get_module_name(&self) -> &str {
27        &self.plugin_name
28    }
29
30    fn compile_module(&self) -> Result<(Store, Module), Error> {
31        let store = new_store();
32        let module = Module::new(&store, &self.bytes)?;
33        Ok((store, module))
34    }
35}
36
37impl RawPluginModuleBytes {
38    pub fn new(identifier: String, bytes: Vec<u8>) -> Self {
39        Self {
40            plugin_name: identifier,
41            bytes,
42        }
43    }
44}
45
46/// A struct for the plugin contains pre-compiled binary.
47/// This is for the cases would like to reuse the compiled module, or either
48/// load from FileSystemCache.
49#[derive(Debug, Serialize, Deserialize, PartialEq)]
50pub struct CompiledPluginModuleBytes {
51    plugin_name: String,
52    #[serde(skip)]
53    bytes: Option<wasmer::Module>,
54    #[serde(skip)]
55    store: Option<wasmer::Store>,
56}
57
58impl Eq for CompiledPluginModuleBytes {}
59
60impl Clone for CompiledPluginModuleBytes {
61    fn clone(&self) -> Self {
62        Self {
63            plugin_name: self.plugin_name.clone(),
64            bytes: self.bytes.clone(),
65            store: Some(Store::new(
66                self.store
67                    .as_ref()
68                    .expect("Store should be available")
69                    .engine()
70                    .clone(),
71            )),
72        }
73    }
74}
75
76impl CompiledPluginModuleBytes {
77    pub fn new(identifier: String, bytes: wasmer::Module, store: wasmer::Store) -> Self {
78        Self {
79            plugin_name: identifier,
80            bytes: Some(bytes),
81            store: Some(store),
82        }
83    }
84}
85
86// Allow to `pre` compile wasm module when there is a raw bytes, want to avoid
87// to skip the compilation step per each trasform.
88impl From<RawPluginModuleBytes> for CompiledPluginModuleBytes {
89    fn from(raw: RawPluginModuleBytes) -> Self {
90        let (store, module) = raw.compile_module().unwrap();
91        Self::new(raw.plugin_name, module, store)
92    }
93}
94
95impl PluginModuleBytes for CompiledPluginModuleBytes {
96    fn get_module_name(&self) -> &str {
97        &self.plugin_name
98    }
99
100    fn compile_module(&self) -> Result<(Store, Module), Error> {
101        Ok((
102            Store::new(
103                self.store
104                    .as_ref()
105                    .expect("Store should be available")
106                    .engine()
107                    .clone(),
108            ),
109            self.bytes
110                .as_ref()
111                .expect("Module should be available")
112                .clone(),
113        ))
114    }
115}