Serializable and debuggable closures.
This library provides macros that wrap closures to make them serializable and debuggable.
use serde_closure::{traits::Fn, Fn};
let one = 1;
let plus_one = Fn!(|x: i32| x + one);
assert_eq!(2, plus_one.call((1,))); // this works on stable and nightly
// assert_eq!(2, plus_one(1)); // this only works on nightly
println!("{:#?}", plus_one);
// prints:
// Fn<main::{{closure}} at main.rs:6:15> {
// one: 1,
// source: "| x : i32 | x + one",
// }
This library aims to work in as simple and safe a way as possible. On stable
Rust the wrapped closures implement
traits::FnOnce
,
traits::FnMut
and traits::Fn
,
and on nightly Rust
std::ops::FnOnce
,
std::ops::FnMut
and
std::ops::Fn
are
implemented as well using the unboxed_closures
and fn_traits
features (rust
issue #29625).
FnOnce
,FnMut
Fn
,Copy
,Clone
, PartialEq
, Eq
, Hash
, PartialOrd
, Ord
, Serialize
,Deserialize
and Debug
.unsafe
.Inferred, non-capturing closure:
|a| a+1
FnMut!(|a| a+1)
Annotated, non-capturing closure:
|a: String| -> String { a.to_uppercase() }
FnMut!(|a: String| -> String { a.to_uppercase() })
Inferred closure, capturing num
:
let mut num = 0;
|a| num += a
let mut num = 0;
FnMut!(|a| num += a)
move
closure, capturing hello
and world
:
let hello = String::from("hello");
let mut world = String::new();
move |name| {
world += (hello.to_uppercase() + name).as_str();
}
let hello = String::from("hello");
let mut world = String::new();
FnMut!(move |name| {
world += (hello.to_uppercase() + name).as_str();
})
There are currently some minor limitations:
my_struct::<>
to disambiguate.error[E0308]: mismatched types
--> tests/test.rs:450:4
|
449 | FnOnce!(move || {
| _____-
450 | | my_struct;
| | ^^^^^^^^^ expected struct `serde_closure::internal::a_variable`, found struct `my_struct`
451 | | });
| |______- in this macro invocation
|
= note: expected type `serde_closure::internal::a_variable`
found type `my_struct`
(MyVariable)
to disambiguate.error: imports cannot refer to local variables
--> tests/test.rs:422:3
|
417 | FnOnce!(move || {
| _____-
418 | | MyVariable;
| | ^^^^^^^^^^
419 | | });
| |______- in this macro invocation
|
function::<>
for(closure)
for closures.Closures created by this crate are unnameable i.e. just like normal closures, there is no Rust syntax available with which to write the type. What this means is that to deserialize a closure, you either need to specify the precise type you're deserializing without naming it (which is possible but not particularly practical), or erase the type by storing it in a trait object.
The serde_traitobject
crate enables trait objects to be safely serialized and sent between other
processes running the same binary.
For example, if you have multiple forks of a process, or the same binary running
on each of a cluster of machines,
serde_traitobject
would
help you to send serializable closures between them. This can be done by
upcasting the closure to a Box<dyn serde_traitobject::Fn()>
, which is
automatically serializable and deserializable with
serde
.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.