async-usercalls 0.7.2

An interface for asynchronous usercalls in SGX enclaves. This is an SGX-only crate, you should compile it with the `x86_64-fortanix-unknown-sgx` target.
use fortanix_sgx_abi::{invoke_with_usercalls, Fd, Result, InsecureTimeInfo};
use std::io;
use std::os::fortanix_sgx::usercalls::raw::{Return, ReturnValue};
use std::os::fortanix_sgx::usercalls::FromSgxResult;

pub struct CbFn<T>(Box<dyn FnOnce(T) + Send + 'static>);

impl<T> CbFn<T> {
    fn call(self, t: T) {
        (self.0)(t);
    }
}

impl<F, T> From<F> for CbFn<T>
    where
        F: FnOnce(T) + Send + 'static,
{
    fn from(f: F) -> Self {
        Self(Box::new(f))
    }
}

macro_rules! cbfn_type {
    ( )                                   => { CbFn<()> };
    ( -> ! )                              => { () };
    ( -> u64 )                            => { CbFn<u64> };
    ( -> (u64, *const InsecureTimeInfo) ) => { CbFn<(u64, *const InsecureTimeInfo)> };
    ( -> (Result, usize) )                => { CbFn<io::Result<usize>> };
    ( -> (Result, u64) )                  => { CbFn<io::Result<u64>> };
    ( -> (Result, Fd) )                   => { CbFn<io::Result<Fd>> };
    ( -> (Result, *mut u8) )              => { CbFn<io::Result<*mut u8>> };
    ( -> Result )                         => { CbFn<io::Result<()>> };
}

macro_rules! call_cbfn {
    ( $cb:ident, $rv:expr, )                                   => { let x: () = $rv; $cb.call(x); };
    ( $cb:ident, $rv:expr, -> ! )                              => { let _: ! = $rv; };
    ( $cb:ident, $rv:expr, -> u64 )                            => { let x: u64 = $rv; $cb.call(x); };
    ( $cb:ident, $rv:expr, -> (u64, *const InsecureTimeInfo) ) => { let x: (u64, *const InsecureTimeInfo) = $rv; $cb.call(x); };
    ( $cb:ident, $rv:expr, -> $t:ty )                          => { let x: $t = $rv; $cb.call(x.from_sgx_result()); };
}

macro_rules! define_callback {
    ($(fn $name:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
        #[allow(unused)]
        #[allow(non_camel_case_types)]
        pub(crate) enum Callback {
            $( $name(cbfn_type! { $(-> $r)* }), )*
        }

        impl Callback {
            pub(crate) fn call(self, ret: Return) {
                match self {$(
                    Callback::$name(_cb) => {
                        call_cbfn!(
                            _cb,
                            ReturnValue::from_registers(stringify!($name), (ret.0, ret.1)),
                            $(-> $r)*
                        );
                    }
                )*}
            }
        }
    };
}

invoke_with_usercalls!(define_callback);