Virtual_machine/
Manager.rs

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
use std::{ffi::CStr, mem::forget, sync::OnceLock};

use wamr_rust_sdk::{
    sys::{wasm_runtime_is_xip_file, wasm_runtime_load, wasm_runtime_register_module},
    value::WasmValue,
};
use File_system::Unique_file_identifier_type;

use crate::{Error_type, Instance_type, Module_type, Registrable_trait, Result_type, Runtime_type};

static Manager_instance: OnceLock<Manager_type> = OnceLock::new();

pub fn Initialize(Registrables: &[&dyn Registrable_trait]) -> &'static Manager_type {
    Manager_instance.get_or_init(|| {
        Manager_type::New(Registrables).expect("Cannot create virtual machine manager")
    });

    Get_instance()
}

pub fn Get_instance() -> &'static Manager_type {
    Manager_instance
        .get()
        .expect("Cannot get virtual machine manager instance before initialization")
}

pub struct Manager_type {
    Runtime: Runtime_type,
}

unsafe impl Send for Manager_type {}

unsafe impl Sync for Manager_type {}

impl Manager_type {
    pub fn New(Registrables: &[&dyn Registrable_trait]) -> Result_type<Self> {
        let mut Runtime_builder = Runtime_type::Builder();

        for Registrable in Registrables {
            Runtime_builder = Runtime_builder.Register(*Registrable);
        }

        let Runtime = Runtime_builder.Build()?;

        let Manager = Self { Runtime };

        for Registrable in Registrables {
            if let Some(Module_binary) = Registrable.Get_binary() {
                Manager.Load_module(Module_binary, Registrable.Is_XIP(), Registrable.Get_name())?;
            }
        }

        Ok(Manager)
    }

    /// Load a module from a buffer for execution in place.
    ///
    /// # Errors
    ///
    /// If the module is not an XIP AOT compiled module or if the module cannot be loaded from the buffer.
    fn Load_module(&self, Buffer: &[u8], XIP: bool, Name: &str) -> Result_type<()> {
        if unsafe { XIP && !wasm_runtime_is_xip_file(Buffer.as_ptr(), Buffer.len() as u32) } {
            return Err(Error_type::Invalid_module);
        }

        unsafe {
            let mut Buffer = if XIP {
                Vec::from_raw_parts(Buffer.as_ptr() as *mut u8, Buffer.len(), Buffer.len())
            } else {
                Buffer.to_vec()
            };

            let mut Error_buffer = [0_i8; 128];

            let Module = wasm_runtime_load(
                Buffer.as_mut_ptr(),
                Buffer.len() as u32,
                Error_buffer.as_mut_ptr(),
                Error_buffer.len() as u32,
            );

            if Module.is_null() {
                return Err(Error_type::Compilation_error(
                    CStr::from_ptr(Error_buffer.as_ptr())
                        .to_string_lossy()
                        .to_string(),
                ));
            }

            if !wasm_runtime_register_module(
                Name.as_ptr() as *const i8,
                Module,
                Error_buffer.as_mut_ptr(),
                Error_buffer.len() as u32,
            ) {
                return Err(Error_type::Internal_error);
            }

            forget(Buffer);
        }

        Ok(())
    }

    pub fn Execute(
        &'static self,
        Buffer: Vec<u8>,
        Stack_size: usize,
        Standard_in: Unique_file_identifier_type,
        Standard_out: Unique_file_identifier_type,
        Standard_error: Unique_file_identifier_type,
    ) -> Result_type<Vec<WasmValue>> {
        let Module = Module_type::From_buffer(
            &self.Runtime,
            Buffer,
            "module",
            Standard_in,
            Standard_out,
            Standard_error,
        )?;

        let Instance = Instance_type::New(&self.Runtime, &Module, Stack_size).unwrap();

        let Result = Instance.Call_main(&vec![])?;

        Ok(Result)
    }
}