use std::fmt;
use std::marker;
use std::mem;
use std::ops::Deref;
#[cfg(feature = "macros")]
pub use wai_bindgen_rust_impl::{export, import};
#[cfg(feature = "async")]
pub use async_trait::async_trait;
#[cfg(feature = "async")]
mod futures;
#[doc(hidden)]
pub use bitflags;
pub struct Handle<T: HandleType> {
val: i32,
_marker: marker::PhantomData<T>,
}
impl<T: HandleType> Handle<T> {
pub fn new(val: T) -> Handle<T>
where
T: LocalHandle,
{
unsafe { Handle::from_raw(T::new(Box::into_raw(Box::new(val)) as i32)) }
}
pub fn into_raw(handle: Handle<T>) -> i32 {
let ret = handle.val;
mem::forget(handle);
ret
}
pub fn as_raw(handle: &Handle<T>) -> i32 {
handle.val
}
pub unsafe fn from_raw(val: i32) -> Handle<T> {
Handle {
val,
_marker: marker::PhantomData,
}
}
}
impl<T: LocalHandle> Deref for Handle<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*(T::get(self.val) as *const T) }
}
}
impl<T: LocalHandle> From<T> for Handle<T> {
fn from(val: T) -> Handle<T> {
Handle::new(val)
}
}
impl<T: HandleType> Clone for Handle<T> {
fn clone(&self) -> Self {
unsafe { Handle::from_raw(T::clone(self.val)) }
}
}
impl<T: HandleType> fmt::Debug for Handle<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Handle").field("val", &self.val).finish()
}
}
impl<T: HandleType> Drop for Handle<T> {
fn drop(&mut self) {
T::drop(self.val);
}
}
pub unsafe trait HandleType {
#[doc(hidden)]
fn clone(val: i32) -> i32;
#[doc(hidden)]
fn drop(val: i32);
}
pub unsafe trait LocalHandle: HandleType {
#[doc(hidden)]
fn new(val: i32) -> i32;
#[doc(hidden)]
fn get(val: i32) -> i32;
}
#[doc(hidden)]
pub mod rt {
use std::alloc::{self, Layout};
#[cfg(feature = "async")]
pub use crate::futures::*;
#[no_mangle]
unsafe extern "C" fn canonical_abi_realloc(
old_ptr: *mut u8,
old_len: usize,
align: usize,
new_len: usize,
) -> *mut u8 {
let layout;
let ptr = if old_len == 0 {
if new_len == 0 {
return align as *mut u8;
}
layout = Layout::from_size_align_unchecked(new_len, align);
alloc::alloc(layout)
} else {
layout = Layout::from_size_align_unchecked(old_len, align);
alloc::realloc(old_ptr, layout, new_len)
};
if ptr.is_null() {
alloc::handle_alloc_error(layout);
}
ptr
}
#[no_mangle]
pub unsafe extern "C" fn canonical_abi_free(ptr: *mut u8, len: usize, align: usize) {
if len == 0 {
return;
}
let layout = Layout::from_size_align_unchecked(len, align);
alloc::dealloc(ptr, layout);
}
macro_rules! as_traits {
($(($trait_:ident $func:ident $ty:ident <=> $($tys:ident)*))*) => ($(
pub fn $func<T: $trait_>(t: T) -> $ty {
t.$func()
}
pub trait $trait_ {
fn $func(self) -> $ty;
}
impl<'a, T: Copy + $trait_> $trait_ for &'a T {
fn $func(self) -> $ty{
(*self).$func()
}
}
$(
impl $trait_ for $tys {
#[inline]
fn $func(self) -> $ty {
self as $ty
}
}
)*
)*)
}
as_traits! {
(AsI64 as_i64 i64 <=> i64 u64)
(AsI32 as_i32 i32 <=> i32 u32 i16 u16 i8 u8 char usize)
(AsF32 as_f32 f32 <=> f32)
(AsF64 as_f64 f64 <=> f64)
}
}