wasmi_c_api/
memory.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use crate::{wasm_extern_t, wasm_memorytype_t, wasm_store_t};
use alloc::boxed::Box;
use core::hint;
use wasmi::{Extern, Memory};

/// A Wasm linear memory.
///
/// Wraps [`Memory`].
#[derive(Clone)]
#[repr(transparent)]
pub struct wasm_memory_t {
    inner: wasm_extern_t,
}

wasmi_c_api_macros::declare_ref!(wasm_memory_t);

/// Type specifying the number of pages of a Wasm linear memory.
pub type wasm_memory_pages_t = u32;

impl wasm_memory_t {
    pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_memory_t> {
        match &e.which {
            Extern::Memory(_) => Some(unsafe { &*(e as *const _ as *const _) }),
            _ => None,
        }
    }

    pub(crate) fn try_from_mut(e: &mut wasm_extern_t) -> Option<&mut wasm_memory_t> {
        match &mut e.which {
            Extern::Memory(_) => Some(unsafe { &mut *(e as *mut _ as *mut _) }),
            _ => None,
        }
    }

    /// Returns the underlying [`Memory`] of the [`wasm_memory_t`].
    fn memory(&self) -> Memory {
        match self.inner.which {
            Extern::Memory(m) => m,
            _ => unsafe { hint::unreachable_unchecked() },
        }
    }
}

/// Creates a new [`wasm_memory_t`] from the given [`wasm_memorytype_t`].
///
/// Wraps [`Memory::new`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_memory_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_memory_new(
    store: &mut wasm_store_t,
    mt: &wasm_memorytype_t,
) -> Option<Box<wasm_memory_t>> {
    let memory = Memory::new(store.inner.context_mut(), mt.ty().ty).ok()?;
    Some(Box::new(wasm_memory_t {
        inner: wasm_extern_t {
            store: store.inner.clone(),
            which: memory.into(),
        },
    }))
}

/// Returns the [`wasm_memory_t`] as mutable reference to [`wasm_extern_t`].
#[no_mangle]
pub extern "C" fn wasm_memory_as_extern(m: &mut wasm_memory_t) -> &mut wasm_extern_t {
    &mut m.inner
}

/// Returns the [`wasm_memory_t`] as shared reference to [`wasm_extern_t`].
#[no_mangle]
pub extern "C" fn wasm_memory_as_extern_const(m: &wasm_memory_t) -> &wasm_extern_t {
    &m.inner
}

/// Returns the [`wasm_memorytype_t`] of the [`wasm_memory_t`].
///
/// Wraps [`Memory::ty`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_memory_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_memory_type(m: &wasm_memory_t) -> Box<wasm_memorytype_t> {
    let ty = m.memory().ty(m.inner.store.context());
    Box::new(wasm_memorytype_t::new(ty))
}

/// Returns the underlying data pointer of the [`wasm_memory_t`].
///
/// Wraps [`Memory::data_ptr`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_memory_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_memory_data(m: &wasm_memory_t) -> *mut u8 {
    m.memory().data_ptr(m.inner.store.context())
}

/// Returns the data buffer size of the [`wasm_memory_t`].
///
/// Wraps [`Memory::data_size`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_memory_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_memory_data_size(m: &wasm_memory_t) -> usize {
    m.memory().data_size(m.inner.store.context())
}

/// Returns the current number of Wasm pages of the [`wasm_memory_t`].
///
/// Wraps [`Memory::size`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_memory_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_memory_size(m: &wasm_memory_t) -> wasm_memory_pages_t {
    m.memory().size(m.inner.store.context())
}

/// Grows the [`wasm_memory_t`] by `delta` Wasm pages.
///
/// Returns `true` if the operation was successful.
///
/// Wraps [`Memory::grow`].
///
/// # Safety
///
/// It is the caller's responsibility not to alias the [`wasm_memory_t`]
/// with its underlying, internal [`WasmStoreRef`](crate::WasmStoreRef).
#[no_mangle]
pub unsafe extern "C" fn wasm_memory_grow(
    m: &mut wasm_memory_t,
    delta: wasm_memory_pages_t,
) -> bool {
    let memory = m.memory();
    let mut store = m.inner.store.context_mut();
    memory.grow(&mut store, delta).is_ok()
}