1 use crate::{CExternType, handle_result, wasm_externtype_t, wasm_limits_t, wasmtime_error_t};
2 use std::convert::TryFrom;
3 use std::{cell::OnceCell, mem::MaybeUninit};
4 use wasmtime::{MemoryType, MemoryTypeBuilder};
5 
6 #[repr(transparent)]
7 #[derive(Clone)]
8 pub struct wasm_memorytype_t {
9     ext: wasm_externtype_t,
10 }
11 
12 wasmtime_c_api_macros::declare_ty!(wasm_memorytype_t);
13 
14 #[derive(Clone)]
15 pub(crate) struct CMemoryType {
16     pub(crate) ty: MemoryType,
17     limits_cache: OnceCell<wasm_limits_t>,
18 }
19 
20 impl wasm_memorytype_t {
new(ty: MemoryType) -> wasm_memorytype_t21     pub(crate) fn new(ty: MemoryType) -> wasm_memorytype_t {
22         wasm_memorytype_t {
23             ext: wasm_externtype_t::from_extern_type(ty.into()),
24         }
25     }
26 
try_from(e: &wasm_externtype_t) -> Option<&wasm_memorytype_t>27     pub(crate) fn try_from(e: &wasm_externtype_t) -> Option<&wasm_memorytype_t> {
28         match &e.which {
29             CExternType::Memory(_) => Some(unsafe { &*(e as *const _ as *const _) }),
30             _ => None,
31         }
32     }
33 
ty(&self) -> &CMemoryType34     pub(crate) fn ty(&self) -> &CMemoryType {
35         match &self.ext.which {
36             CExternType::Memory(f) => &f,
37             _ => unsafe { std::hint::unreachable_unchecked() },
38         }
39     }
40 }
41 
42 impl CMemoryType {
new(ty: MemoryType) -> CMemoryType43     pub(crate) fn new(ty: MemoryType) -> CMemoryType {
44         CMemoryType {
45             ty,
46             limits_cache: OnceCell::new(),
47         }
48     }
49 }
50 
51 #[unsafe(no_mangle)]
wasm_memorytype_new(limits: &wasm_limits_t) -> Box<wasm_memorytype_t>52 pub extern "C" fn wasm_memorytype_new(limits: &wasm_limits_t) -> Box<wasm_memorytype_t> {
53     Box::new(wasm_memorytype_t::new(MemoryType::new(
54         limits.min,
55         limits.max(),
56     )))
57 }
58 
59 #[unsafe(no_mangle)]
wasm_memorytype_limits(mt: &wasm_memorytype_t) -> &wasm_limits_t60 pub extern "C" fn wasm_memorytype_limits(mt: &wasm_memorytype_t) -> &wasm_limits_t {
61     let mt = mt.ty();
62     mt.limits_cache.get_or_init(|| wasm_limits_t {
63         min: u32::try_from(mt.ty.minimum()).unwrap(),
64         max: u32::try_from(mt.ty.maximum().unwrap_or(u64::from(u32::max_value()))).unwrap(),
65     })
66 }
67 
68 #[unsafe(no_mangle)]
wasmtime_memorytype_new( minimum: u64, maximum_specified: bool, maximum: u64, memory64: bool, shared: bool, page_size_log2: u8, ret: &mut MaybeUninit<Box<wasm_memorytype_t>>, ) -> Option<Box<wasmtime_error_t>>69 pub extern "C" fn wasmtime_memorytype_new(
70     minimum: u64,
71     maximum_specified: bool,
72     maximum: u64,
73     memory64: bool,
74     shared: bool,
75     page_size_log2: u8,
76     ret: &mut MaybeUninit<Box<wasm_memorytype_t>>,
77 ) -> Option<Box<wasmtime_error_t>> {
78     let maximum = if maximum_specified {
79         Some(maximum)
80     } else {
81         None
82     };
83 
84     handle_result(
85         MemoryTypeBuilder::default()
86             .min(minimum)
87             .max(maximum)
88             .memory64(memory64)
89             .shared(shared)
90             .page_size_log2(page_size_log2)
91             .build(),
92         |ty| {
93             ret.write(Box::new(wasm_memorytype_t::new(ty)));
94         },
95     )
96 }
97 
98 #[unsafe(no_mangle)]
wasmtime_memorytype_minimum(mt: &wasm_memorytype_t) -> u6499 pub extern "C" fn wasmtime_memorytype_minimum(mt: &wasm_memorytype_t) -> u64 {
100     mt.ty().ty.minimum()
101 }
102 
103 #[unsafe(no_mangle)]
wasmtime_memorytype_maximum(mt: &wasm_memorytype_t, out: &mut u64) -> bool104 pub extern "C" fn wasmtime_memorytype_maximum(mt: &wasm_memorytype_t, out: &mut u64) -> bool {
105     match mt.ty().ty.maximum() {
106         Some(max) => {
107             *out = max;
108             true
109         }
110         None => false,
111     }
112 }
113 
114 #[unsafe(no_mangle)]
wasmtime_memorytype_is64(mt: &wasm_memorytype_t) -> bool115 pub extern "C" fn wasmtime_memorytype_is64(mt: &wasm_memorytype_t) -> bool {
116     mt.ty().ty.is_64()
117 }
118 
119 #[unsafe(no_mangle)]
wasmtime_memorytype_isshared(mt: &wasm_memorytype_t) -> bool120 pub extern "C" fn wasmtime_memorytype_isshared(mt: &wasm_memorytype_t) -> bool {
121     mt.ty().ty.is_shared()
122 }
123 
124 #[unsafe(no_mangle)]
wasmtime_memorytype_page_size(mt: &wasm_memorytype_t) -> u64125 pub extern "C" fn wasmtime_memorytype_page_size(mt: &wasm_memorytype_t) -> u64 {
126     mt.ty().ty.page_size()
127 }
128 
129 #[unsafe(no_mangle)]
wasmtime_memorytype_page_size_log2(mt: &wasm_memorytype_t) -> u8130 pub extern "C" fn wasmtime_memorytype_page_size_log2(mt: &wasm_memorytype_t) -> u8 {
131     mt.ty().ty.page_size_log2()
132 }
133 
134 #[unsafe(no_mangle)]
wasm_memorytype_as_externtype(ty: &wasm_memorytype_t) -> &wasm_externtype_t135 pub extern "C" fn wasm_memorytype_as_externtype(ty: &wasm_memorytype_t) -> &wasm_externtype_t {
136     &ty.ext
137 }
138 
139 #[unsafe(no_mangle)]
wasm_memorytype_as_externtype_const( ty: &wasm_memorytype_t, ) -> &wasm_externtype_t140 pub extern "C" fn wasm_memorytype_as_externtype_const(
141     ty: &wasm_memorytype_t,
142 ) -> &wasm_externtype_t {
143     &ty.ext
144 }
145