cosmian_wit_bindgen_rust/
lib.rs

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