linera_wit_bindgen_guest_rust/
lib.rs

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