pub mod sendable;
pub mod addressing;
mod erased;
pub use erased::ErasedCallable;
mod error;
pub use error::CallError;
mod envelope;
pub(crate) use envelope::Envelope;
use crate::ffi::callback::addressing::resolveRelative;
use crate::ffi::types::primitive::DynamicList;
use crate::ffi::types::Type;
use crate::ffi::types::Value;
use crate::ffi::types::primitive::{Primitive};
use serde::{Serialize};
#[doc(hidden)]
pub mod __reexport
{
pub use bincode;
pub use serde;
}
pub trait Callable<Args, Output>: Send
{
fn call(&self, args: Args) -> Output;
}
pub fn decode(bytes: &[u8]) -> Result<ErasedCallable, CallError>
{
let (envelope, _): (Envelope, usize) = bincode::serde::decode_from_slice(bytes, bincode::config::standard())
.map_err(|e| CallError::Decode(e.to_string()))?;
type DecodeFn = fn(u64, u64, &[u8]) -> Result<ErasedCallable, CallError>;
let absoluteAddr: usize = resolveRelative(envelope.relativeOffset);
let decodeFn: DecodeFn = unsafe{ std::mem::transmute(absoluteAddr) };
decodeFn(envelope.siteTag, envelope.argsOutputTag, &envelope.bytes)
}
#[macro_export]
macro_rules! callback
{
($scope:expr, [$($name:ident : $ty:ty),* $(,)?] |$($argName:ident : $argTy:ty),* $(,)?| -> $retTy:ty $body:block) =>
{
{
#[allow(unused_variables, unused_mut)]
fn __callTyped(
state: &($($ty,)*),
args: &$crate::ffi::types::primitive::DynamicList
) -> $retTy
{
let ($($name,)*) = state.clone();
let mut __i: usize = 0;
$(
let $argName: $argTy = args
.get(__i)
.expect(concat!("callback arg ", stringify!($argName), ": expected ", stringify!($argTy)));
__i += 1;
)*
let result: $retTy = { $body };
result
}
fn __callDecode(
siteTag: u64,
argsOutputTag: u64,
bytes: &[u8]
) -> ::std::result::Result<
$crate::ffi::callback::ErasedCallable,
$crate::ffi::callback::CallError
>
{
let expectedSiteTag: u64 = $crate::ffi::callback::addressing::tagOf(
concat!(file!(), ":", line!(), ":", column!())
);
if siteTag != expectedSiteTag {
return ::std::result::Result::Err(
$crate::ffi::callback::CallError::TypeMismatch { tag: siteTag }
);
}
let expectedTypesTag: u64 = $crate::ffi::callback::addressing::typesTagOf(
&[ $( <$argTy as $crate::ffi::types::primitive::Primitive>::TypeTag ),* ],
&<$retTy as $crate::ffi::types::primitive::Primitive>::TypeTag
);
if argsOutputTag != expectedTypesTag {
return ::std::result::Result::Err(
$crate::ffi::callback::CallError::ArgsOutputMismatch
);
}
let (state, _): (($($ty,)*), usize) =
$crate::ffi::callback::__reexport::bincode::serde::decode_from_slice(
bytes,
$crate::ffi::callback::__reexport::bincode::config::standard()
).map_err(|e| $crate::ffi::callback::CallError::Decode(
::std::string::ToString::to_string(&e)
))?;
::std::result::Result::Ok(
$crate::ffi::callback::ErasedCallable::fromStateAndFn(state, __callTyped)
)
}
let siteTag: u64 = $crate::ffi::callback::addressing::tagOf(
concat!(file!(), ":", line!(), ":", column!())
);
let relativeOffset: usize = $crate::ffi::callback::addressing::relativeOffsetOf(
__callDecode as *const () as usize
);
let argTypes: ::std::vec::Vec<$crate::ffi::types::Type> =
vec![ $( <$argTy as $crate::ffi::types::primitive::Primitive>::TypeTag ),* ];
let returnType: $crate::ffi::types::Type =
<$retTy as $crate::ffi::types::primitive::Primitive>::TypeTag;
$scope.callback(
$crate::ffi::callback::sendable::Sendable::new(
relativeOffset,
siteTag,
argTypes,
returnType,
($($name,)*),
__callTyped
)
)
}
};
}