wasmer_wit_bindgen_rust/
lib.rs

1use std::fmt;
2use std::marker;
3use std::mem;
4use std::ops::Deref;
5
6#[cfg(feature = "macros")]
7pub use wasmer_wit_bindgen_rust_impl::{export, import};
8
9#[cfg(feature = "async")]
10pub use async_trait::async_trait;
11#[cfg(feature = "async")]
12mod futures;
13
14// Re-export `bitflags` so that we can reference it from macros.
15#[doc(hidden)]
16pub use bitflags;
17
18/// A type for handles to resources that appear in exported functions.
19///
20/// This type is used as `Handle<T>` for argument types and return values of
21/// exported functions when exposing a Rust-defined resource. A `Handle<T>`
22/// represents an owned reference count on the interface-types-managed resource.
23/// It's similar to an `Rc<T>` in Rust. Internally a `Handle<T>` can provide
24/// access to `&T` when `T` is defined in the current module.
25pub struct Handle<T: HandleType> {
26    val: i32,
27    _marker: marker::PhantomData<T>,
28}
29
30impl<T: HandleType> Handle<T> {
31    /// Creates a new handle around the specified value.
32    ///
33    /// Note that the lifetime of `T` will afterwards be managed by the
34    /// interface types runtime. The host may hold references to `T` that wasm
35    /// isn't necessarily aware of, preventing its destruction. Nevertheless
36    /// though the `Drop for T` implementation will still be run when there are
37    /// no more references to `T`.
38    pub fn new(val: T) -> Handle<T>
39    where
40        T: LocalHandle,
41    {
42        unsafe { Handle::from_raw(T::new(Box::into_raw(Box::new(val)) as i32)) }
43    }
44
45    /// Consumes a handle and returns the underlying raw wasm i32 descriptor.
46    ///
47    /// Note that this, if used improperly, will leak the resource `T`. This
48    /// generally should be avoided unless you're calling raw ABI bindings and
49    /// managing the lifetime manually.
50    pub fn into_raw(handle: Handle<T>) -> i32 {
51        let ret = handle.val;
52        mem::forget(handle);
53        ret
54    }
55
56    /// Returns the raw underlying handle value for this handle.
57    ///
58    /// This typically isn't necessary to interact with, but can be useful when
59    /// interacting with raw ABI bindings.
60    pub fn as_raw(handle: &Handle<T>) -> i32 {
61        handle.val
62    }
63
64    /// Unsafely assumes that the given integer descriptor is a handle for `T`.
65    ///
66    /// This is unsafe because no validation is performed to ensure that `val`
67    /// is actually a valid descriptor for `T`.
68    pub unsafe fn from_raw(val: i32) -> Handle<T> {
69        Handle {
70            val,
71            _marker: marker::PhantomData,
72        }
73    }
74}
75
76impl<T: LocalHandle> Deref for Handle<T> {
77    type Target = T;
78
79    fn deref(&self) -> &T {
80        unsafe { &*(T::get(self.val) as *const T) }
81    }
82}
83
84impl<T: LocalHandle> From<T> for Handle<T> {
85    fn from(val: T) -> Handle<T> {
86        Handle::new(val)
87    }
88}
89
90impl<T: HandleType> Clone for Handle<T> {
91    fn clone(&self) -> Self {
92        unsafe { Handle::from_raw(T::clone(self.val)) }
93    }
94}
95
96impl<T: HandleType> fmt::Debug for Handle<T> {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        f.debug_struct("Handle").field("val", &self.val).finish()
99    }
100}
101
102impl<T: HandleType> Drop for Handle<T> {
103    fn drop(&mut self) {
104        T::drop(self.val);
105    }
106}
107
108/// A trait for types that can show up as the `T` in `Handle<T>`.
109///
110/// This trait is automatically synthesized for exported handles and typically
111/// shouldn't be implemented manually.
112pub unsafe trait HandleType {
113    #[doc(hidden)]
114    fn clone(val: i32) -> i32;
115    #[doc(hidden)]
116    fn drop(val: i32);
117}
118
119/// An extension of the [`HandleType`] trait for locally-defined types.
120///
121/// This trait may not stick around forever...
122pub unsafe trait LocalHandle: HandleType {
123    #[doc(hidden)]
124    fn new(val: i32) -> i32;
125    #[doc(hidden)]
126    fn get(val: i32) -> i32;
127}
128
129#[doc(hidden)]
130pub mod rt {
131    use std::alloc::{self, Layout};
132
133    #[cfg(feature = "async")]
134    pub use crate::futures::*;
135
136    #[no_mangle]
137    unsafe extern "C" fn canonical_abi_realloc(
138        old_ptr: *mut u8,
139        old_len: usize,
140        align: usize,
141        new_len: usize,
142    ) -> *mut u8 {
143        let layout;
144        let ptr = if old_len == 0 {
145            if new_len == 0 {
146                return align as *mut u8;
147            }
148            layout = Layout::from_size_align_unchecked(new_len, align);
149            alloc::alloc(layout)
150        } else {
151            layout = Layout::from_size_align_unchecked(old_len, align);
152            alloc::realloc(old_ptr, layout, new_len)
153        };
154        if ptr.is_null() {
155            alloc::handle_alloc_error(layout);
156        }
157        return ptr;
158    }
159
160    #[no_mangle]
161    pub unsafe extern "C" fn canonical_abi_free(ptr: *mut u8, len: usize, align: usize) {
162        if len == 0 {
163            return;
164        }
165        let layout = Layout::from_size_align_unchecked(len, align);
166        alloc::dealloc(ptr, layout);
167    }
168
169    macro_rules! as_traits {
170        ($(($trait_:ident $func:ident $ty:ident <=> $($tys:ident)*))*) => ($(
171            pub fn $func<T: $trait_>(t: T) -> $ty {
172                t.$func()
173            }
174
175            pub trait $trait_ {
176                fn $func(self) -> $ty;
177            }
178
179            impl<'a, T: Copy + $trait_> $trait_ for &'a T {
180                fn $func(self) -> $ty{
181                    (*self).$func()
182                }
183            }
184
185            $(
186                impl $trait_ for $tys {
187                    #[inline]
188                    fn $func(self) -> $ty {
189                        self as $ty
190                    }
191                }
192            )*
193
194        )*)
195    }
196
197    as_traits! {
198        (AsI64 as_i64 i64 <=> i64 u64)
199        (AsI32 as_i32 i32 <=> i32 u32 i16 u16 i8 u8 char usize)
200        (AsF32 as_f32 f32 <=> f32)
201        (AsF64 as_f64 f64 <=> f64)
202    }
203}