#![doc(html_root_url = "https://docs.rs/serde_closure/0.1.4")]
#![feature(unboxed_closures, fn_traits, core_intrinsics)]
#![warn(
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unused_import_braces,
unused_qualifications,
unused_results,
clippy::pedantic
)]
#![allow(clippy::inline_always, clippy::doc_markdown)]
use relative::Code;
use serde::{Deserialize, Serialize};
use std::{cmp, fmt, hash, intrinsics, marker, mem, ops};
#[derive(Serialize, Deserialize)]
#[serde(
bound(serialize = "E: Serialize, F: 'static"),
bound(deserialize = "E: Deserialize<'de>, F: 'static")
)]
pub struct FnOnce<E, F> {
env: E,
addr: Code<F>,
#[serde(skip)]
marker: marker::PhantomData<F>,
}
impl<E, F> FnOnce<E, F> {
#[doc(hidden)]
#[inline(always)]
pub unsafe fn private_construct(env: E, addr: *const (), _: &F) -> Self {
Self {
env,
addr: Code::from(addr),
marker: marker::PhantomData,
}
}
}
impl<E, T, F, O> ops::FnOnce<T> for FnOnce<E, F>
where
F: ops::FnOnce(E, T) -> O,
{
type Output = O;
#[inline(always)]
extern "rust-call" fn call_once(self, args: T) -> Self::Output {
unsafe { mem::transmute::<*const (), fn(E, T) -> F::Output>(self.addr.to()) }
.call_once((self.env, args))
}
}
impl<E, T> Clone for FnOnce<E, T>
where
E: Clone,
{
fn clone(&self) -> Self {
Self {
env: self.env.clone(),
addr: self.addr,
marker: marker::PhantomData,
}
}
}
impl<E, T> Copy for FnOnce<E, T> where E: Copy {}
impl<E, T> PartialEq for FnOnce<E, T>
where
E: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.env == other.env && self.addr == other.addr
}
}
impl<E, T> Eq for FnOnce<E, T> where E: Eq {}
impl<E, T> hash::Hash for FnOnce<E, T>
where
E: hash::Hash,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.env.hash(state);
self.addr.hash(state);
}
}
impl<E, T> PartialOrd for FnOnce<E, T>
where
E: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.env
.partial_cmp(&other.env)
.map(|x| x.then_with(|| self.addr.cmp(&other.addr)))
}
}
impl<E, T> Ord for FnOnce<E, T>
where
E: Ord,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.env
.cmp(&other.env)
.then_with(|| self.addr.cmp(&other.addr))
}
}
impl<E, T> fmt::Debug for FnOnce<E, T>
where
E: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("FnOnce")
.field("env", &self.env)
.field(unsafe { intrinsics::type_name::<T>() }, &self.addr)
.finish()
}
}
#[derive(Serialize, Deserialize)]
#[serde(
bound(serialize = "E: Serialize, F: 'static"),
bound(deserialize = "E: Deserialize<'de>, F: 'static")
)]
pub struct FnMut<E, F> {
env: E,
addr: Code<F>,
#[serde(skip)]
marker: marker::PhantomData<F>,
}
impl<E, F> FnMut<E, F> {
#[doc(hidden)]
#[inline(always)]
pub unsafe fn private_construct(env: E, addr: *const (), _: &F) -> Self {
Self {
env,
addr: Code::from(addr),
marker: marker::PhantomData,
}
}
}
impl<E, T, F, O> ops::FnOnce<T> for FnMut<E, F>
where
F: ops::FnOnce(&mut E, T) -> O,
{
type Output = O;
#[inline(always)]
extern "rust-call" fn call_once(mut self, args: T) -> Self::Output {
unsafe { mem::transmute::<*const (), fn(&mut E, T) -> F::Output>(self.addr.to()) }
.call_once((&mut self.env, args))
}
}
impl<E, T, F, O> ops::FnMut<T> for FnMut<E, F>
where
F: ops::FnOnce(&mut E, T) -> O,
{
#[inline(always)]
extern "rust-call" fn call_mut(&mut self, args: T) -> Self::Output {
unsafe { mem::transmute::<*const (), fn(&mut E, T) -> F::Output>(self.addr.to()) }
.call_mut((&mut self.env, args))
}
}
impl<E, T> Clone for FnMut<E, T>
where
E: Clone,
{
fn clone(&self) -> Self {
Self {
env: self.env.clone(),
addr: self.addr,
marker: marker::PhantomData,
}
}
}
impl<E, T> Copy for FnMut<E, T> where E: Copy {}
impl<E, T> PartialEq for FnMut<E, T>
where
E: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.env == other.env && self.addr == other.addr
}
}
impl<E, T> Eq for FnMut<E, T> where E: Eq {}
impl<E, T> hash::Hash for FnMut<E, T>
where
E: hash::Hash,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.env.hash(state);
self.addr.hash(state);
}
}
impl<E, T> PartialOrd for FnMut<E, T>
where
E: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.env
.partial_cmp(&other.env)
.map(|x| x.then_with(|| self.addr.cmp(&other.addr)))
}
}
impl<E, T> Ord for FnMut<E, T>
where
E: Ord,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.env
.cmp(&other.env)
.then_with(|| self.addr.cmp(&other.addr))
}
}
impl<E, T> fmt::Debug for FnMut<E, T>
where
E: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("FnMut")
.field("env", &self.env)
.field(unsafe { intrinsics::type_name::<T>() }, &self.addr)
.finish()
}
}
#[derive(Serialize, Deserialize)]
#[serde(
bound(serialize = "E: Serialize, F: 'static"),
bound(deserialize = "E: Deserialize<'de>, F: 'static")
)]
pub struct Fn<E, F> {
env: E,
addr: Code<F>,
#[serde(skip)]
marker: marker::PhantomData<F>,
}
impl<E, F> Fn<E, F> {
#[doc(hidden)]
#[inline(always)]
pub unsafe fn private_construct(env: E, addr: *const (), _: &F) -> Self {
Self {
env,
addr: Code::from(addr),
marker: marker::PhantomData,
}
}
}
impl<E, T, F, O> ops::FnOnce<T> for Fn<E, F>
where
F: ops::FnOnce(&E, T) -> O,
{
type Output = O;
#[inline(always)]
extern "rust-call" fn call_once(self, args: T) -> Self::Output {
unsafe { mem::transmute::<*const (), fn(&E, T) -> F::Output>(self.addr.to()) }
.call_once((&self.env, args))
}
}
impl<E, T, F, O> ops::FnMut<T> for Fn<E, F>
where
F: ops::FnOnce(&E, T) -> O,
{
#[inline(always)]
extern "rust-call" fn call_mut(&mut self, args: T) -> Self::Output {
unsafe { mem::transmute::<*const (), fn(&E, T) -> F::Output>(self.addr.to()) }
.call_mut((&self.env, args))
}
}
impl<E, T, F, O> ops::Fn<T> for Fn<E, F>
where
F: ops::FnOnce(&E, T) -> O,
{
#[inline(always)]
extern "rust-call" fn call(&self, args: T) -> Self::Output {
unsafe { mem::transmute::<*const (), fn(&E, T) -> F::Output>(self.addr.to()) }
.call((&self.env, args))
}
}
impl<E, T> Clone for Fn<E, T>
where
E: Clone,
{
fn clone(&self) -> Self {
Self {
env: self.env.clone(),
addr: self.addr,
marker: marker::PhantomData,
}
}
}
impl<E, T> Copy for Fn<E, T> where E: Copy {}
impl<E, T> PartialEq for Fn<E, T>
where
E: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.env == other.env && self.addr == other.addr
}
}
impl<E, T> Eq for Fn<E, T> where E: Eq {}
impl<E, T> hash::Hash for Fn<E, T>
where
E: hash::Hash,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.env.hash(state);
self.addr.hash(state);
}
}
impl<E, T> PartialOrd for Fn<E, T>
where
E: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.env
.partial_cmp(&other.env)
.map(|x| x.then_with(|| self.addr.cmp(&other.addr)))
}
}
impl<E, T> Ord for Fn<E, T>
where
E: Ord,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.env
.cmp(&other.env)
.then_with(|| self.addr.cmp(&other.addr))
}
}
impl<E, T> fmt::Debug for Fn<E, T>
where
E: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Fn")
.field("env", &self.env)
.field(unsafe { intrinsics::type_name::<T>() }, &self.addr)
.finish()
}
}
#[macro_export]
macro_rules! FnOnce {
([$( $env:ident ,)* ] move |$( $arg:pat => $ty:ty, $t:ident $u:ty,)*| -> $o:ty $block:block) => ({
let env = ($($env,)*);
fn apply_env_type<E,O,$($t,)*>(_ :&E, f: fn(E,($($u,)*))->O) -> fn(E,($($u,)*))->O {f}
let closure = apply_env_type(&env, move|($($env,)*),($($arg,)*):($($ty,)*)|->$o { $block });
if false {
#[allow(unreachable_code)]
let _: $o = closure(env,unreachable!());
}
let fn_ptr: fn(_,($($ty,)*))->$o = closure;
if false {
#[allow(unreachable_code)]
let _: $o = fn_ptr(env,unreachable!());
}
#[allow(unused_unsafe)]
unsafe {
$crate::FnOnce::private_construct(
env,
fn_ptr as *const (),
&fn_ptr,
)
}
});
([$( $env:ident ,)* ] ref |$( $arg:pat => $ty:ty, $t:ident $u:ty,)*| -> $o:ty $block:block) => ({
let env = ($(&$env,)*);
fn apply_env_type<E,O,$($t,)*>(_ :&E, f: fn(E,($($u,)*))->O) -> fn(E,($($u,)*))->O {f}
let closure = apply_env_type(&env, |($($env,)*),($($arg,)*):($($ty,)*)|->$o { $block });
if false {
#[allow(unreachable_code)]
let _: $o = closure(env,unreachable!());
}
let fn_ptr: fn(_,($($ty,)*))->$o = closure;
if false {
#[allow(unreachable_code)]
let _: $o = fn_ptr(env,unreachable!());
}
#[allow(unused_unsafe)]
unsafe {
$crate::FnOnce::private_construct(
env,
fn_ptr as *const (),
&fn_ptr,
)
}
});
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:pat, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => &mut _, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:pat, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => &_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => _, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:ident: $type_:ty, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => $type_, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:ident: $type_:ty, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => $type_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: &mut $type_:ty, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => &mut $type_, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: & $type_:ty, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => & $type_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: $type_:ty, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat=> $type_:ty, $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:pat $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => &mut _, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:pat $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => &_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => _, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => $type_, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => $type_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: &mut $type_:ty $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => &mut $type_, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: & $type_:ty $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => & $type_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat=> $type_:ty $(,)*| $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($($ss:ident)*) || $block:expr) => { FnOnce!([$($env,)*] $move |$($arg => $type,$t $u,)*| -> _ { $block } ) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($($ss:ident)*) || -> $o:ty $block:block) => { FnOnce!([$($env,)*] $move |$($arg => $type,$t $u,)*| -> $o $block ) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| () |$( $tail:tt )*) => { compile_error!("This macro unfortunately only handles up to 32 arguments. Easily extendable, fork and bump it if you really need that many!") };
([$( $env:ident ),* $(,)* ] move | $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
(move | $( $tail:tt )*) => { FnOnce!(@args [] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
([$( $env:ident ),* $(,)* ] move || $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
(move || $( $tail:tt )*) => { FnOnce!(@args [] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
([$( $env:ident ),* $(,)* ] | $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
(| $( $tail:tt )*) => { FnOnce!(@args [] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
([$( $env:ident ),* $(,)* ] || $( $tail:tt )*) => { FnOnce!(@args [$($env,)*] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
(|| $( $tail:tt )*) => { FnOnce!(@args [] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
}
#[macro_export]
macro_rules! FnMut {
([$( $env:ident ,)* ] move |$( $arg:pat => $ty:ty, $t:ident $u:ty,)*| -> $o:ty $block:block) => ({
let mut env = ($($env,)*);
fn apply_env_type<E,O,$($t,)*>(_ :&E, f: fn(&mut E,($($u,)*))->O) -> fn(&mut E,($($u,)*))->O {f}
let closure = apply_env_type(&env, move|&mut ($(ref mut $env,)*):&mut _,($($arg,)*):($($ty,)*)|->$o { $block });
if false {
#[allow(unreachable_code)]
let _: $o = closure(&mut env,unreachable!());
}
let fn_ptr: fn(&mut _,($($ty,)*))->$o = closure;
if false {
#[allow(unreachable_code)]
let _: $o = fn_ptr(&mut env,unreachable!());
}
#[allow(unused_unsafe)]
unsafe {
$crate::FnMut::private_construct(
env,
fn_ptr as *const (),
&fn_ptr,
)
}
});
([$( $env:ident ,)* ] ref |$( $arg:pat => $ty:ty, $t:ident $u:ty,)*| -> $o:ty $block:block) => ({
let mut env = ($(&mut $env,)*);
fn apply_env_type<E,O,$($t,)*>(_ :&E, f: fn(&mut E,($($u,)*))->O) -> fn(&mut E,($($u,)*))->O {f}
let closure = apply_env_type(&env, |&mut ($(&mut ref mut $env,)*):&mut _,($($arg,)*):($($ty,)*)|->$o { $block });
if false {
#[allow(unreachable_code)]
let _: $o = closure(&mut env,unreachable!());
}
let fn_ptr: fn(&mut _,($($ty,)*))->$o = closure;
if false {
#[allow(unreachable_code)]
let _: $o = fn_ptr(&mut env,unreachable!());
}
#[allow(unused_unsafe)]
unsafe {
$crate::FnMut::private_construct(
env,
fn_ptr as *const (),
&fn_ptr,
)
}
});
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:pat, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => &mut _, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:pat, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => &_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => _, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:ident: $type_:ty, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => $type_, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:ident: $type_:ty, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => $type_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: &mut $type_:ty, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => &mut $type_, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: & $type_:ty, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => & $type_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: $type_:ty, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat=> $type_:ty, $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:pat $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => &mut _, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:pat $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => &_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => _, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => $type_, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => $type_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: &mut $type_:ty $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => &mut $type_, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: & $type_:ty $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => & $type_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat=> $type_:ty $(,)*| $( $tail:tt )*) => { FnMut!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($($ss:ident)*) || $block:expr) => { FnMut!([$($env,)*] $move |$($arg => $type,$t $u,)*| -> _ { $block } ) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($($ss:ident)*) || -> $o:ty $block:block) => { FnMut!([$($env,)*] $move |$($arg => $type,$t $u,)*| -> $o $block ) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| () |$( $tail:tt )*) => { compile_error!("This macro unfortunately only handles up to 32 arguments. Easily extendable, fork and bump it if you really need that many!") };
([$( $env:ident ),* $(,)* ] move | $( $tail:tt )*) => { FnMut!(@args [$($env,)*] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
(move | $( $tail:tt )*) => { FnMut!(@args [] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
([$( $env:ident ),* $(,)* ] move || $( $tail:tt )*) => { FnMut!(@args [$($env,)*] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
(move || $( $tail:tt )*) => { FnMut!(@args [] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
([$( $env:ident ),* $(,)* ] | $( $tail:tt )*) => { FnMut!(@args [$($env,)*] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
(| $( $tail:tt )*) => { FnMut!(@args [] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
([$( $env:ident ),* $(,)* ] || $( $tail:tt )*) => { FnMut!(@args [$($env,)*] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
(|| $( $tail:tt )*) => { FnMut!(@args [] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
}
#[macro_export]
macro_rules! Fn {
([$( $env:ident ,)* ] move |$( $arg:pat => $ty:ty, $t:ident $u:ty,)*| -> $o:ty $block:block) => ({
let env = ($($env,)*);
fn apply_env_type<E,O,$($t,)*>(_ :&E, f: fn(&E,($($u,)*))->O) -> fn(&E,($($u,)*))->O {f}
let closure = apply_env_type(&env, move|&($(ref $env,)*):&_,($($arg,)*):($($ty,)*)|->$o { $block });
if false {
#[allow(unreachable_code)]
let _: $o = closure(&env,unreachable!());
}
let fn_ptr: fn(&_,($($ty,)*))->$o = closure;
if false {
#[allow(unreachable_code)]
let _: $o = fn_ptr(&env,unreachable!());
}
#[allow(unused_unsafe)]
unsafe {
$crate::Fn::private_construct(
env,
fn_ptr as *const (),
&fn_ptr,
)
}
});
([$( $env:ident ,)* ] ref |$( $arg:pat => $ty:ty, $t:ident $u:ty,)*| -> $o:ty $block:block) => ({
let env = ($(&$env,)*);
fn apply_env_type<E,O,$($t,)*>(_ :&E, f: fn(&E,($($u,)*))->O) -> fn(&E,($($u,)*))->O {f}
let closure = apply_env_type(&env, |&($($env,)*):&_,($($arg,)*):($($ty,)*)|->$o { $block });
if false {
#[allow(unreachable_code)]
let _: $o = closure(&env,unreachable!());
}
let fn_ptr: fn(&_,($($ty,)*))->$o = closure;
if false {
#[allow(unreachable_code)]
let _: $o = fn_ptr(&env,unreachable!());
}
#[allow(unused_unsafe)]
unsafe {
$crate::Fn::private_construct(
env,
fn_ptr as *const (),
&fn_ptr,
)
}
});
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:pat, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => &mut _, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:pat, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => &_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => _, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:ident: $type_:ty, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => $type_, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:ident: $type_:ty, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => $type_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: &mut $type_:ty, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => &mut $type_, $s &mut $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: & $type_:ty, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => & $type_, $s & $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: $type_:ty, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat=> $type_:ty, $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) | $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:pat $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => &mut _, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:pat $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => &_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => _, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |&mut $arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* &mut $arg_ => $type_, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |& $arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* & $arg_ => $type_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: &mut $type_:ty $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => &mut $type_, $s &mut $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: & $type_:ty $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => & $type_, $s & $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:ident: $type_:ty $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($s:ident $($ss:ident)*) |$arg_:pat=> $type_:ty $(,)*| $( $tail:tt )*) => { Fn!(@args [$($env,)*] $move |$($arg => $type,$t $u,)* $arg_ => $type_, $s $s,| ($($ss)*) || $( $tail )*) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($($ss:ident)*) || $block:expr) => { Fn!([$($env,)*] $move |$($arg => $type,$t $u,)*| -> _ { $block } ) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| ($($ss:ident)*) || -> $o:ty $block:block) => { Fn!([$($env,)*] $move |$($arg => $type,$t $u,)*| -> $o $block ) };
(@args [$( $env:ident ,)* ] $move:ident |$( $arg:pat => $type:ty, $t:ident $u:ty,)*| () |$( $tail:tt )*) => { compile_error!("This macro unfortunately only handles up to 32 arguments. Easily extendable, fork and bump it if you really need that many!") };
([$( $env:ident ),* $(,)* ] move | $( $tail:tt )*) => { Fn!(@args [$($env,)*] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
(move | $( $tail:tt )*) => { Fn!(@args [] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
([$( $env:ident ),* $(,)* ] move || $( $tail:tt )*) => { Fn!(@args [$($env,)*] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
(move || $( $tail:tt )*) => { Fn!(@args [] move | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
([$( $env:ident ),* $(,)* ] | $( $tail:tt )*) => { Fn!(@args [$($env,)*] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
(| $( $tail:tt )*) => { Fn!(@args [] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) | $( $tail )*) };
([$( $env:ident ),* $(,)* ] || $( $tail:tt )*) => { Fn!(@args [$($env,)*] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
(|| $( $tail:tt )*) => { Fn!(@args [] ref | | (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31 T32) || $( $tail )*) };
}
#[cfg(test)]
mod tests {
#![allow(clippy::items_after_statements, clippy::type_complexity)]
use bincode;
use serde::{de::DeserializeOwned, Serialize};
use serde_json;
use std::{env, fmt, mem, process, str};
#[test]
fn fn_ptr_size() {
assert_eq!(mem::size_of::<usize>(), mem::size_of::<fn()>());
}
#[test]
fn fnonce() {
fn test<
F: FnOnce(usize, &usize, &mut usize, String, &String, &mut String) -> String
+ Serialize
+ DeserializeOwned
+ PartialEq
+ Eq
+ Clone
+ fmt::Debug,
>(
f: F,
) {
let deserialized: F =
serde_json::from_str(&serde_json::to_string(&f).unwrap()).unwrap();
let deserialized2: F = bincode::deserialize(&bincode::serialize(&f).unwrap()).unwrap();
assert_eq!(f, deserialized);
assert_eq!(deserialized, deserialized2);
assert_eq!(f, deserialized2);
let test = |f: F| {
let mut a = 3;
let mut b = String::from("ghi");
assert_eq!(
f.clone()(
1,
&2,
&mut a,
String::from("abc"),
&String::from("def"),
&mut b
),
"3qwerty129abcdefghiqwertyabcdef"
);
a += 6;
b += "pqr";
assert_eq!(
f.clone()(
4,
&5,
&mut a,
String::from("jkl"),
&String::from("mno"),
&mut b
),
"3qwerty4527jklmnoghiqwertyabcdefpqrqwertyjklmno"
);
a += 9;
b += "yz";
assert_eq!(
f(
7,
&8,
&mut a,
String::from("stu"),
&String::from("vwx"),
&mut b
),
"3qwerty7854stuvwxghiqwertyabcdefpqrqwertyjklmnoyzqwertystuvwx"
);
};
test(f);
test(deserialized);
test(deserialized2);
}
let (a, b) = (3_usize, String::from("qwerty"));
let a = FnOnce!([a,b] move |c,d:&_,e:&mut _,f:String,g:&String,h:&mut String| -> String {
let a: usize = a;
let b: String = b;
*e += a+c+*d;
*h += (b.clone()+f.as_str()+g.as_str()).as_str();
format!("{}{}{}{}{}{}{}{}", a, b, c, d, e, f, g, h)
});
test(a);
let b = FnOnce!(|a| {
println!("{:?}", a);
});
b(0_usize);
let c = FnOnce!(|arg: String| {
println!("{}", arg);
});
let _ = (c, c);
}
#[test]
fn fnmut() {
fn test<
F: FnMut(usize, &usize, &mut usize, String, &String, &mut String) -> String
+ Serialize
+ DeserializeOwned
+ PartialEq
+ Eq
+ Clone
+ fmt::Debug,
>(
mut f: F,
) {
let mut deserialized: F =
serde_json::from_str(&serde_json::to_string(&f).unwrap()).unwrap();
let mut deserialized2: F =
bincode::deserialize(&bincode::serialize(&f).unwrap()).unwrap();
assert_eq!(f, deserialized);
assert_eq!(deserialized, deserialized2);
assert_eq!(f, deserialized2);
let test = |f: &mut F| {
let mut a = 3;
let mut b = String::from("ghi");
assert_eq!(
f(
1,
&2,
&mut a,
String::from("abc"),
&String::from("def"),
&mut b
),
"12qwertyghiqwertyabcdef129abcdefghiqwertyabcdef"
);
a += 6;
b += "pqr";
assert_eq!(f(4, &5, &mut a, String::from("jkl"), &String::from("mno"), &mut b), "48qwertyghiqwertyabcdefghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmno4536jklmnoghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmno");
a += 9;
b += "yz";
assert_eq!(f(7, &8, &mut a, String::from("stu"), &String::from("vwx"), &mut b), "156qwertyghiqwertyabcdefghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmnoghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmnoyzqwertyghiqwertyabcdefghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmnostuvwx78108stuvwxghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmnoyzqwertyghiqwertyabcdefghiqwertyabcdefpqrqwertyghiqwertyabcdefjklmnostuvwx");
};
test(&mut f);
test(&mut deserialized);
test(&mut deserialized2);
assert_eq!(f, deserialized);
assert_eq!(deserialized, deserialized2);
assert_eq!(f, deserialized2);
}
let (a, b) = (3_usize, String::from("qwerty"));
let a = FnMut!([a,b] move |c,d:&_,e:&mut _,f:String,g:&String,h:&mut String| -> String {
*e += *a+c+*d;
*a += *e;
*h += (b.clone()+f.as_str()+g.as_str()).as_str();
*b += h.as_str();
format!("{}{}{}{}{}{}{}{}", a, b, c, d, e, f, g, h)
});
test(a);
fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
where
F: FnMut(&mut St) -> Option<A> + Serialize,
{
Unfold {
_f: f,
_state: initial_state,
}
}
struct Unfold<St, F> {
_f: F,
_state: St,
}
let _ = unfold(0_usize, FnMut!(|acc: &mut _| Some(*acc)));
let x = 123_usize;
let c = FnMut!([x] move|arg:String|{
println!("{} {}", x, arg);
});
let _ = (c, c);
}
#[test]
fn fnref() {
fn test<
F: Fn(
usize,
&usize,
&mut usize,
&usize,
&mut usize,
String,
&String,
&mut String,
) -> String
+ Serialize
+ DeserializeOwned
+ PartialEq
+ Eq
+ Clone
+ fmt::Debug,
>(
mut f: F,
) {
let mut deserialized: F =
serde_json::from_str(&serde_json::to_string(&f).unwrap()).unwrap();
let mut deserialized2: F =
bincode::deserialize(&bincode::serialize(&f).unwrap()).unwrap();
assert_eq!(f, deserialized);
assert_eq!(deserialized, deserialized2);
assert_eq!(f, deserialized2);
let test = |f: &mut F| {
let mut a = 3;
let mut b = String::from("ghi");
let mut x = 11;
assert_eq!(
f(
1,
&2,
&mut a,
&10,
&mut x,
String::from("abc"),
&String::from("def"),
&mut b
),
"3qwerty129abcdefghiqwertyabcdef"
);
a += 6;
b += "pqr";
x += 13;
assert_eq!(
f(
4,
&5,
&mut a,
&12,
&mut x,
String::from("jkl"),
&String::from("mno"),
&mut b
),
"3qwerty4527jklmnoghiqwertyabcdefpqrqwertyjklmno"
);
a += 9;
b += "yz";
x += 15;
assert_eq!(
f(
7,
&8,
&mut a,
&14,
&mut x,
String::from("stu"),
&String::from("vwx"),
&mut b
),
"3qwerty7854stuvwxghiqwertyabcdefpqrqwertyjklmnoyzqwertystuvwx"
);
};
test(&mut f);
test(&mut deserialized);
test(&mut deserialized2);
assert_eq!(f, deserialized);
assert_eq!(deserialized, deserialized2);
assert_eq!(f, deserialized2);
}
let (a, b) = (3_usize, String::from("qwerty"));
{
assert_eq!(
Fn!([a,b] |c:usize,d:&usize,e:&mut usize,&_x:&usize,&mut _y:&mut usize,f:String,g:&String,h:&mut String| -> String {
*e += *a+c+*d;
*h += (b.clone()+f.as_str()+g.as_str()).as_str();
format!("{}{}{}{}{}{}{}{}", a, b, c, d, e, f, g, h)
})(
0,
&1,
&mut 2,
&3,
&mut 4,
String::from("a"),
&String::from("b"),
&mut String::from("c")
),
"3qwerty016abcqwertyab"
);
}
let x = Fn!([a,b] move |c,d:&_,e:&mut _,&_x,&mut _y,f:String,g:&String,h:&mut String| -> String {
*e += *a+c+*d;
*h += (b.clone()+f.as_str()+g.as_str()).as_str();
format!("{}{}{}{}{}{}{}{}", a, b, c, d, e, f, g, h)
});
test(x);
fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
where
F: Fn(&mut St) -> Option<A> + Serialize,
{
Unfold {
_f: f,
_state: initial_state,
}
}
struct Unfold<St, F> {
_f: F,
_state: St,
}
let _ = unfold(0_usize, Fn!(|acc: &mut _| Some(*acc)));
let x = 123_usize;
let c = unsafe {
Fn!([x] move|arg:String|{
println!("{} {}", x, arg);
})
};
let _ = (c, c);
}
#[test]
fn multi_process() {
let exe = env::current_exe().unwrap();
if let Ok(x) = env::var("SPAWNED_TOKEN_SERDECLOSURE") {
let mut f: super::FnMut<
(usize, String),
for<'r, 's, 't0, 't1, 't2> fn(
&'r mut (usize, String),
(
usize,
&'s usize,
&'t0 mut usize,
String,
&'t1 String,
&'t2 mut String,
),
) -> String,
> = serde_json::from_str(&x).unwrap();
let mut a = 3;
let mut b = String::from("ghi");
assert_eq!(
f(
1,
&2,
&mut a,
String::from("abc"),
&String::from("def"),
&mut b
),
"12qwertyghiqwertyabcdef129abcdefghiqwertyabcdef"
);
println!("success_token_serdeclosure {:?}", f);
return;
}
let (a, b) = (3_usize, String::from("qwerty"));
let a: super::FnMut<
(usize, String),
for<'r, 's, 't0, 't1, 't2> fn(
&'r mut (usize, String),
(
usize,
&'s usize,
&'t0 mut usize,
String,
&'t1 String,
&'t2 mut String,
),
) -> String,
> = FnMut!([a,b] move |c,d:&_,e:&mut _,f:String,g:&String,h:&mut String| -> String {
*e += *a+c+*d;
*a += *e;
*h += (b.clone()+f.as_str()+g.as_str()).as_str();
*b += h.as_str();
format!("{}{}{}{}{}{}{}{}", a, b, c, d, e, f, g, h)
});
for i in 0..100 {
let output = process::Command::new(&exe)
.arg("--nocapture")
.arg("--exact")
.arg("tests::multi_process")
.env(
"SPAWNED_TOKEN_SERDECLOSURE",
serde_json::to_string(&a).unwrap(),
)
.output()
.unwrap();
if !str::from_utf8(&output.stdout)
.unwrap()
.contains("success_token_serdeclosure")
|| !output.status.success()
{
panic!("{}: {:?}", i, output);
}
}
}
}