#closures #serialization #serde #distributed #debugging

serde_closure

可序列化和可调试的闭包。该库提供了宏,可以将闭包包装起来使其可序列化和可调试

25次发布

0.3.3 2022年11月24日
0.3.2 2020年8月5日
0.3.1 2020年7月14日
0.2.10 2020年2月5日
0.1.2 2018年7月30日

编码类别中排名第316

Download history 254/week @ 2024-03-12 483/week @ 2024-03-19 141/week @ 2024-03-26 254/week @ 2024-04-02 66/week @ 2024-04-09 126/week @ 2024-04-16 119/week @ 2024-04-23 151/week @ 2024-04-30 114/week @ 2024-05-07 112/week @ 2024-05-14 108/week @ 2024-05-21 146/week @ 2024-05-28 83/week @ 2024-06-04 75/week @ 2024-06-11 112/week @ 2024-06-18 80/week @ 2024-06-25

每月下载量370
19crate中(14个直接使用)

MIT/Apache

39KB
692

serde_closure

Crates.io MIT / Apache 2.0 licensed Build Status

📖 文档 | 💬 聊天

可序列化和可调试的闭包。

该库提供了宏,可以将闭包包装起来使其可序列化和可调试。

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",
// }

该库旨在尽可能简单和安全地工作。在稳定版Rust中,包装的闭包实现了 traits::FnOncetraits::FnMuttraits::Fn,在夜间版Rust中,使用 unboxed_closuresfn_traits 功能(rust issue #29625)实现了 std::ops::FnOncestd::ops::FnMutstd::ops::Fn

  • 有三个宏,分别是 FnOnceFnMutFn,分别对应Rust的三个闭包类型。
  • 将你的闭包用宏之一包装起来,它现在将实现 CopyClonePartialEqEqHashPartialOrdOrdSerializeDeserializeDebug
  • 以下列出了一些细微的语法限制。
  • 此包有一个不可避免但已记录且合理的 unsafe 使用。

包装闭包的示例

推断的、非捕获闭包

|a| a+1
FnMut!(|a| a+1)

注解的、非捕获闭包

|a: String| -> String { a.to_uppercase() }
FnMut!(|a: String| -> String { a.to_uppercase() })

推断的闭包,捕获 num

let mut num = 0;
|a| num += a
let mut num = 0;
FnMut!(|a| num += a)

move 闭包,捕获 helloworld

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();
})

限制

目前存在一些细微的限制

  • 以小写字母开头的类型可能需要与变量区分。如果您看到如下错误,请修正类型的大小写,或者通过添加 my_struct::<> 来消除歧义。
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) 包装它以消除歧义。
error: imports cannot refer to local variables
   --> tests/test.rs:422:3
    |
417 |       FnOnce!(move || {
    |  _____-
418 | |         MyVariable;
    | |         ^^^^^^^^^^
419 | |     });
    | |______- in this macro invocation
    |
  • 闭包内调用的函数和闭包可能需要消除歧义。这可以通过与上述相同的方式完成,使用 function::<> 为函数和 (closure) 为闭包。

进程间的序列化

此包创建的闭包是不可命名的 - 即,与普通闭包一样,没有 Rust 语法可以用来编写类型。这意味着要反序列化闭包,您要么需要指定正在反序列化的确切类型而不命名它(这是可能的但不太实用),或者通过将类型存储在一个 trait object 中来 擦除 类型。

serde_traitobject 包允许 trait objects 在运行相同二进制文件的其他进程之间安全地序列化和传递。

例如,如果您有多个进程的副本,或者在每个集群机器上运行的相同二进制文件,serde_traitobject 将帮助您在它们之间发送可序列化的闭包。这可以通过将闭包向上转换为 Box<dyn serde_traitobject::Fn()> 来实现,它是自动可序列化和反序列化的,与 serde 一起。

许可证

根据以下任一项获得许可

根据您的选择。

除非您明确表示否则,您根据Apache-2.0许可证定义的任何有意提交以包含在工作中的贡献,将如上双许可,不附加任何额外条款或条件。

依赖项

~0.4–1MB
~22K SLoC