File: runtime.rs

package info (click to toggle)
rust-swc-core 35.0.0~ds-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 62,816 kB
  • sloc: javascript: 873; xml: 538; sh: 358; makefile: 35; python: 5
file content (131 lines) | stat: -rw-r--r-- 3,874 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Plugin runtime abstract

use std::{any::Any, fmt, path::Path};

/// Runtime FFI Value
pub type Value = i32;

/// Opaque module cache
pub struct ModuleCache(pub Box<dyn Any + Send + Sync>);

/// Module cache or raw bytes module
pub enum Module {
    Cache(ModuleCache),
    Bytes(Box<[u8]>),
}

/// Plugin function define
pub struct Func {
    /// Number of parameters and return values
    pub sign: (u8, u8),
    /// The closure
    pub func: Box<dyn Fn(&mut dyn Caller<'_>, &[Value], &mut [Value]) + Send + Sync>,
}

/// Plugin runtime abstract
pub trait Runtime: fmt::Debug + Send + Sync {
    /// An identifier used to identify the runtime implement,
    /// which should include the runtime name and version.
    fn identifier(&self) -> &'static str;

    /// Preprocess raw bytes into module cache
    ///
    /// Note that it is not mandatory to implement AOT. It can just be loaded as
    /// an object.
    fn prepare_module(&self, bytes: &[u8]) -> anyhow::Result<ModuleCache>;

    /// Initialize the plugin instance
    ///
    /// * `name` and `envs` parameters are module name and environment variable
    ///   pairs. They can be ignored for non-wasi modules.
    /// * `imports` parameters should be provided as `env` module.
    /// * The runtime should call the `__get_transform_plugin_core_pkg_diag`
    ///   function once after instantiation to check that initialization was
    ///   completed correctly.
    fn init(
        &self,
        name: &str,
        imports: Vec<(String, Func)>,
        envs: Vec<(String, String)>,
        module: Module,
    ) -> anyhow::Result<Box<dyn Instance>>;

    /// Clone module cache
    ///
    /// If the runtime does not allow clone, then it can return `None`.
    fn clone_cache(&self, _cache: &ModuleCache) -> Option<ModuleCache> {
        None
    }

    /// Load a module from file
    ///
    /// # Safety
    ///
    /// This function is marked as unsafe, allow to load trusted module cache
    /// without verification.
    unsafe fn load_cache(&self, _path: &Path) -> Option<ModuleCache> {
        None
    }

    /// Store a module to file
    fn store_cache(&self, _path: &Path, _cache: &ModuleCache) -> anyhow::Result<()> {
        Ok(())
    }
}

/// Instance Accessor
pub trait Caller<'a> {
    /// Read data from instance memory
    fn read_buf(&self, ptr: u32, buf: &mut [u8]) -> anyhow::Result<()>;

    /// Write data to instance memory
    fn write_buf(&mut self, ptr: u32, buf: &[u8]) -> anyhow::Result<()>;

    /// Allocate memory in instance
    fn alloc(&mut self, size: u32) -> anyhow::Result<u32>;

    /// Free memory in instance
    fn free(&mut self, ptr: u32, size: u32) -> anyhow::Result<u32>;
}

/// Plugin instance
pub trait Instance: Send + Sync {
    /// Execute transform.
    ///
    /// The program parameter should use [Caller::alloc] to allocate
    /// and write `PluginSerializedBytes` data.
    fn transform(
        &mut self,
        program_ptr: u32,
        program_len: u32,
        unresolved_mark: u32,
        should_enable_comments_proxy: u32,
    ) -> anyhow::Result<u32>;

    /// Get instance accessor
    fn caller(&mut self) -> anyhow::Result<Box<dyn Caller<'_> + '_>>;

    /// Export Module cache
    fn cache(&self) -> Option<ModuleCache>;

    /// Perform cleanup operations
    fn cleanup(&mut self) -> anyhow::Result<()> {
        Ok(())
    }
}

impl Func {
    /// Create a plugin function from closure
    pub fn from_fn<const A: usize, const R: usize, F>(f: F) -> Self
    where
        F: Fn(&mut dyn Caller<'_>, [i32; A]) -> [i32; R] + Send + Sync + 'static,
    {
        Func {
            sign: (A.try_into().unwrap(), R.try_into().unwrap()),
            func: Box::new(move |store, args, rv| {
                let args = args.try_into().unwrap();
                rv.copy_from_slice(&f(store, args));
            }),
        }
    }
}