#[macro_export]
macro_rules! func {
($f:ident :: <$($gen:ty),*>, $fn_type:ty) => {{
let fn_val:$fn_type = $f::<$($gen),*>;
let ptr = fn_val as *const ();
let sig = std::any::type_name_of_val(&fn_val);
let type_id = std::any::TypeId::of::<$fn_type>();
unsafe { FuncPtr::new_with_type_id(ptr, sig, type_id) }
}};
($f:expr, $fn_type:ty) => {{
let fn_val:$fn_type = $f;
let ptr = fn_val as *const ();
let sig = std::any::type_name_of_val(&fn_val);
let type_id = std::any::TypeId::of::<$fn_type>();
unsafe { FuncPtr::new_with_type_id(ptr, sig, type_id) }
}};
($($tt:tt)*) => {{
$crate::__func_checked!($($tt)*)
}};
}
#[macro_export]
macro_rules! func_unchecked {
($f:ident :: <$($gen:ty),*>) => {{
let fn_val = $f::<$($gen),*>;
let ptr = fn_val as *const ();
FuncPtr::new(ptr, "")
}};
($f:expr) => {{
let fn_val = $f;
let ptr = fn_val as *const ();
FuncPtr::new(ptr, "")
}};
(fn ( $f:expr ) ( $($arg_ty:ty),* ) -> $ret:ty) => {{
$crate::func!($f, fn($($arg_ty),*) -> $ret)
}};
(fn ( $f:expr ) ( $($arg_ty:ty),* )) => {{
$crate::func!($f, fn($($arg_ty),*))
}};
}
#[macro_export]
macro_rules! closure {
($closure:expr, $fn_type:ty) => {{
let fn_val: $fn_type = $closure;
let sig = std::any::type_name_of_val(&fn_val);
let type_id = std::any::TypeId::of::<$fn_type>();
unsafe { FuncPtr::new_with_type_id(fn_val as *const (), sig, type_id) }
}};
}
#[macro_export]
macro_rules! closure_unchecked {
($closure:expr, $fn_type:ty) => {{
let fn_val: $fn_type = $closure;
FuncPtr::new(fn_val as *const (), "")
}};
}
#[doc(hidden)]
pub fn __assert_future_output<Fut, T>(_: &mut Fut)
where
Fut: std::future::Future<Output = T>,
{
}
#[doc(hidden)]
pub fn __type_id_of_val<T: 'static>(_: &T) -> std::any::TypeId {
std::any::TypeId::of::<T>()
}
#[macro_export]
macro_rules! async_func {
($expr:expr, $ty:ty) => {{
let mut __fut = $expr;
let _ = __assert_future_output::<_, $ty>(&mut __fut);
let sig = std::any::type_name::<fn() -> std::task::Poll<$ty>>();
(std::pin::pin!(__fut), sig)
}};
}
#[macro_export]
macro_rules! async_func_unchecked {
($expr:expr) => {
std::pin::pin!($expr)
};
}
#[macro_export]
macro_rules! async_return {
($val:expr, $ty:ty) => {{
fn generated_poll_fn() -> std::task::Poll<$ty> {
std::task::Poll::Ready($val)
}
$crate::func!(generated_poll_fn, fn() -> std::task::Poll<$ty>)
}};
}
#[macro_export]
macro_rules! async_return_unchecked {
($val:expr, $ty:ty) => {{
fn generated_poll_fn() -> std::task::Poll<$ty> {
std::task::Poll::Ready($val)
}
$crate::func_unchecked!(generated_poll_fn)
}};
}
#[macro_export]
macro_rules! fake {
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
{ $($assign)* }
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
unreachable!()
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
$ret_val
} else {
unreachable!()
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) {
if $cond {
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) {
if true {
{ $($assign)* }
} else {
unreachable!()
}
}
let f: fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> (),
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
unreachable!()
}
}
let f: fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: fn($($arg_name:ident: $arg_ty:ty),*) -> ()
) => {{
let verifier = CallCountVerifier::Dummy;
fn fake($($arg_name: $arg_ty),*) {
if true { } else { unreachable!() }
}
let f: fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
$ret_val
} else {
unreachable!()
}
}
let f: unsafe fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
unreachable!()
}
}
let f: unsafe fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: unsafe fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: unsafe fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> (),
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
unreachable!()
}
}
let f: unsafe fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe fn fake($($arg_name: $arg_ty),*) {
if true {
{ $($assign)* }
} else {
unreachable!()
}
}
let f: unsafe fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe fn($($arg_name:ident: $arg_ty:ty),*) -> ()
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe fn fake($($arg_name: $arg_ty),*) {
if true { } else { unreachable!() }
}
let f: unsafe fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
{ $($assign)* }
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "C" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if $cond {
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if true {
{ $($assign)* }
} else {
unreachable!()
}
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
unreachable!()
}
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "C" fn($($arg_name:ident: $arg_ty:ty),*) -> ()
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "C" fn fake($($arg_name: $arg_ty),*) {
if true { } else { unreachable!() }
}
let f: unsafe extern "C" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
{ $($assign)* }
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
when: $cond:expr,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
assign: { $($assign:tt)* },
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
{ $($assign)* }
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> $ret:ty,
returns: $ret_val:expr
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) -> $ret {
if true {
$ret_val
} else {
unreachable!()
}
}
let f: unsafe extern "system" fn($($arg_ty),*) -> $ret = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if $cond {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
when: $cond:expr,
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if $cond {
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* }
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if true {
{ $($assign)* }
} else {
unreachable!()
}
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
assign: { $($assign:tt)* },
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
{ $($assign)* }
} else {
panic!("Fake function defined at {}:{}:{} called with unexpected arguments", file!(), line!(), column!());
}
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> (),
times: $expected:expr
) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static FAKE_COUNTER: AtomicUsize = AtomicUsize::new(0);
let verifier = CallCountVerifier::WithCount { counter: &FAKE_COUNTER, expected: $expected };
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if true {
let prev = FAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
if prev >= $expected {
panic!("Fake function defined at {}:{}:{} called more times than expected", file!(), line!(), column!());
}
} else {
unreachable!()
}
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
(
func_type: unsafe extern "system" fn($($arg_name:ident: $arg_ty:ty),*) -> ()
) => {{
let verifier = CallCountVerifier::Dummy;
unsafe extern "system" fn fake($($arg_name: $arg_ty),*) {
if true { } else { unreachable!() }
}
let f: unsafe extern "system" fn($($arg_ty),*) = fake;
let raw_ptr = f as *const ();
(unsafe { FuncPtr::new(raw_ptr, std::any::type_name_of_val(&f)) }, verifier)
}};
}
#[macro_export]
macro_rules! verify_func {
(fn ($func:expr)($($param:ty),*) -> $ret:ty) => {{
#[allow(non_snake_case)]
fn __injectorpp_infer_ret<__InjectorppRet>(
_f: fn($($param),*) -> __InjectorppRet,
) -> fn($($param),*) -> __InjectorppRet {
_f
}
#[allow(non_snake_case)]
fn __injectorpp_must_match<__InjectorppT>(
_a: &mut __InjectorppT,
_b: &mut __InjectorppT,
) {
}
let mut __injectorpp_natural = __injectorpp_infer_ret($func);
let mut __injectorpp_user: fn($($param),*) -> $ret = $func;
__injectorpp_must_match(&mut __injectorpp_natural, &mut __injectorpp_user);
}};
}