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
use alloc::rc::Rc;
use core::ptr::NonNull;

use crate::error::{Error, Result};
use crate::module::ParsedModule;
use crate::runtime::Runtime;

#[derive(Debug)]
struct DropEnvironment(NonNull<ffi::M3Environment>);

impl Drop for DropEnvironment {
    fn drop(&mut self) {
        unsafe { ffi::m3_FreeEnvironment(self.0.as_ptr()) };
    }
}

/// An environment is required to construct [`Runtime`]s from.
#[derive(Debug, Clone)]
pub struct Environment(Rc<DropEnvironment>);

impl Environment {
    /// Creates a new environment.
    ///
    /// # Errors
    ///
    /// This function will error on memory allocation failure.
    #[inline]
    pub fn new() -> Result<Self> {
        unsafe { NonNull::new(ffi::m3_NewEnvironment()) }
            .ok_or_else(Error::malloc_error)
            .map(|raw| Environment(Rc::new(DropEnvironment(raw))))
    }

    /// Creates a new runtime with the given stack size in slots.
    ///
    /// # Errors
    ///
    /// This function will error on memory allocation failure.
    #[inline]
    pub fn create_runtime(&self, stack_size: u32) -> Result<Runtime> {
        Runtime::new(self, stack_size)
    }

    /// Parses a wasm module from raw bytes.
    #[inline]
    pub fn parse_module(&self, bytes: &[u8]) -> Result<ParsedModule> {
        ParsedModule::parse(self, bytes)
    }

    #[inline]
    pub(crate) fn as_ptr(&self) -> ffi::IM3Environment {
        (self.0).0.as_ptr()
    }
}

impl core::cmp::Eq for Environment {}
impl core::cmp::PartialEq for Environment {
    fn eq(&self, &Environment(ref other): &Environment) -> bool {
        alloc::rc::Rc::ptr_eq(&self.0, other)
    }
}

#[test]
fn create_and_drop_env() {
    assert!(Environment::new().is_ok());
}