#[macro_export]
macro_rules! input {
(@inner $input:expr, $cursor:expr,) => {};
(@size $size:expr, ) => { $size };
(@inner $input:expr, $cursor:expr, $var:ident: u8, $($rest:tt)*) => {
let $var = $input[$cursor];
input!(@inner $input, $cursor + 1, $($rest)*);
};
(@size $size:expr, $var:ident: u8, $($rest:tt)*) => {
input!(@size $size + 1, $($rest)*)
};
(@inner $input:expr, $cursor:expr, $var:ident: u64, $($rest:tt)*) => {
let $var = u64::from_le_bytes($input[$cursor..$cursor + 8].try_into().unwrap());
input!(@inner $input, $cursor + 8, $($rest)*);
};
(@size $size:expr, $var:ident: u64, $($rest:tt)*) => {
input!(@size $size + 8, $($rest)*)
};
(@inner $input:expr, $cursor:expr, $var:ident: u32, $($rest:tt)*) => {
let $var = u32::from_le_bytes($input[$cursor..$cursor + 4].try_into().unwrap());
input!(@inner $input, $cursor + 4, $($rest)*);
};
(@size $size:expr, $var:ident: u32, $($rest:tt)*) => {
input!(@size $size + 4, $($rest)*)
};
(@inner $input:expr, $cursor:expr, $var:ident: [u8],) => {
let $var = &$input[$cursor..];
};
(@inner $input:expr, $cursor:expr, $var:ident: [u8; $n:expr], $($rest:tt)*) => {
let $var = &$input[$cursor..$cursor+$n];
input!(@inner $input, $cursor + $n, $($rest)*);
};
(@inner $input:expr, $cursor:expr, $var:ident: &[u8; $n:expr], $($rest:tt)*) => {
let $var: &[u8; $n] = &$input[$cursor..$cursor+$n].try_into().unwrap();
input!(@inner $input, $cursor + $n, $($rest)*);
};
(@size $size:expr, $var:ident: [u8; $n:expr], $($rest:tt)*) => {
input!(@size $size + $n, $($rest)*)
};
(@size $size:expr, $var:ident: &[u8; $n:expr], $($rest:tt)*) => {
input!(@size $size + $n, $($rest)*)
};
($buffer:ident, $size:expr, $($rest:tt)*) => {
let mut $buffer = [0u8; $size];
let input_size = $crate::HostFnImpl::call_data_size();
let $buffer = &mut &mut $buffer[..$size.min(input_size as usize)];
$crate::HostFnImpl::call_data_copy($buffer, 0);
input!(@inner $buffer, 0, $($rest)*);
};
($buffer: ident, $($rest:tt)*) => {
input!($buffer, input!(@size 0, $($rest)*), $($rest)*);
};
($($rest:tt)*) => {
input!(buffer, $($rest)*);
};
}
#[macro_export]
macro_rules! output {
($output: ident, $buffer: expr, $host_fn:path, $($arg:expr),*) => {
let mut $output = $buffer;
let $output = &mut &mut $output[..];
$host_fn($($arg,)* $output);
};
}
#[macro_export]
macro_rules! unwrap_output {
($output: ident, $buffer: expr, $host_fn:path, $($arg:expr),*) => {
let mut $output = $buffer;
let $output = &mut &mut $output[..];
$host_fn($($arg,)* $output).unwrap();
};
}
#[macro_export]
macro_rules! u64_output {
($host_fn:path, $($arg:expr),*) => {{
let mut buffer = [1u8; 32];
$host_fn($($arg,)* &mut buffer);
assert!(buffer[8..].iter().all(|&x| x == 0));
u64::from_le_bytes(buffer[..8].try_into().unwrap())
}};
}