{"id":16687826,"url":"https://github.com/alecmocatta/serde_closure","last_synced_at":"2025-05-08T00:39:59.230Z","repository":{"id":49405402,"uuid":"141326735","full_name":"alecmocatta/serde_closure","owner":"alecmocatta","description":"Serialisable closures for Rust.","archived":false,"fork":false,"pushed_at":"2022-11-24T12:49:55.000Z","size":195,"stargazers_count":64,"open_issues_count":4,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-08T00:39:52.584Z","etag":null,"topics":["closures","distributed","rust","serde"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alecmocatta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-17T18:12:46.000Z","updated_at":"2024-09-09T04:57:52.000Z","dependencies_parsed_at":"2023-01-23T17:46:12.999Z","dependency_job_id":null,"html_url":"https://github.com/alecmocatta/serde_closure","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecmocatta%2Fserde_closure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecmocatta%2Fserde_closure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecmocatta%2Fserde_closure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecmocatta%2Fserde_closure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alecmocatta","download_url":"https://codeload.github.com/alecmocatta/serde_closure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252978668,"owners_count":21834910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["closures","distributed","rust","serde"],"created_at":"2024-10-12T15:25:14.596Z","updated_at":"2025-05-08T00:39:59.207Z","avatar_url":"https://github.com/alecmocatta.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# serde_closure\n\n[![Crates.io](https://img.shields.io/crates/v/serde_closure.svg?maxAge=86400)](https://crates.io/crates/serde_closure)\n[![MIT / Apache 2.0 licensed](https://img.shields.io/crates/l/serde_closure.svg?maxAge=2592000)](#License)\n[![Build Status](https://dev.azure.com/alecmocatta/serde_closure/_apis/build/status/tests?branchName=master)](https://dev.azure.com/alecmocatta/serde_closure/_build?definitionId=10)\n\n[📖 Docs](https://docs.rs/serde_closure) | [💬 Chat](https://constellation.zulipchat.com/#narrow/stream/213236-subprojects)\n\nSerializable and debuggable closures.\n\nThis library provides macros that wrap closures to make them serializable and\ndebuggable.\n\n```rust\nuse serde_closure::{traits::Fn, Fn};\n\nlet one = 1;\nlet plus_one = Fn!(|x: i32| x + one);\n\nassert_eq!(2, plus_one.call((1,))); // this works on stable and nightly\n// assert_eq!(2, plus_one(1));      // this only works on nightly\nprintln!(\"{:#?}\", plus_one);\n\n// prints:\n// Fn\u003cmain::{{closure}} at main.rs:6:15\u003e {\n//     one: 1,\n//     source: \"| x : i32 | x + one\",\n// }\n```\n\nThis library aims to work in as simple and safe a way as possible. On stable\nRust the wrapped closures implement\n[`traits::FnOnce`](https://docs.rs/serde_closure/0.3/serde_closure/traits/trait.FnOnce.html),\n[`traits::FnMut`](https://docs.rs/serde_closure/0.3/serde_closure/traits/trait.FnMut.html)\nand [`traits::Fn`](https://docs.rs/serde_closure/0.3/serde_closure/traits/trait.Fn.html),\nand on nightly Rust\n[`std::ops::FnOnce`](https://doc.rust-lang.org/std/ops/trait.FnOnce.html),\n[`std::ops::FnMut`](https://doc.rust-lang.org/std/ops/trait.FnMut.html) and\n[`std::ops::Fn`](https://doc.rust-lang.org/std/ops/trait.Fn.html) are\nimplemented as well using the `unboxed_closures` and `fn_traits` features (rust\nissue [#29625](https://github.com/rust-lang/rust/issues/29625)).\n\n * There are three macros,\n   [`FnOnce`](https://docs.rs/serde_closure/0.3/serde_closure/macro.FnOnce.html),\n   [`FnMut`](https://docs.rs/serde_closure/0.3/serde_closure/macro.FnMut.html)\n   and [`Fn`](https://docs.rs/serde_closure/0.3/serde_closure/macro.Fn.html),\n   corresponding to the three types of Rust closure.\n * Wrap your closure with one of the macros and it will now implement `Copy`,\n   `Clone`, `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`, `Serialize`,\n   `Deserialize` and `Debug`.\n * There are some minor syntax limitations, which are documented below.\n * This crate has one unavoidable but documented and sound usage of\n   `unsafe`.\n\n## Examples of wrapped closures\n**Inferred, non-capturing closure:**\n```rust\n|a| a+1\n```\n```rust\nFnMut!(|a| a+1)\n```\n\n**Annotated, non-capturing closure:**\n```rust\n|a: String| -\u003e String { a.to_uppercase() }\n```\n```rust\nFnMut!(|a: String| -\u003e String { a.to_uppercase() })\n```\n\n**Inferred closure, capturing `num`:**\n```rust\nlet mut num = 0;\n|a| num += a\n```\n```rust\nlet mut num = 0;\nFnMut!(|a| num += a)\n```\n\n**`move` closure, capturing `hello` and `world`:**\n```rust\nlet hello = String::from(\"hello\");\nlet mut world = String::new();\nmove |name| {\n    world += (hello.to_uppercase() + name).as_str();\n}\n```\n```rust\nlet hello = String::from(\"hello\");\nlet mut world = String::new();\nFnMut!(move |name| {\n    world += (hello.to_uppercase() + name).as_str();\n})\n```\n\n## Limitations\nThere are currently some minor limitations:\n\n * Use of types that start with a lowercase letter need might need to be\n   disambiguated from variables. If you see an error like the following, fix the\n   case of the type, or append it with `my_struct::\u003c\u003e` to disambiguate.\n```text\nerror[E0308]: mismatched types\n   --\u003e tests/test.rs:450:4\n    |\n449 |       FnOnce!(move || {\n    |  _____-\n450 | |         my_struct;\n    | |         ^^^^^^^^^ expected struct `serde_closure::internal::a_variable`, found struct `my_struct`\n451 | |     });\n    | |______- in this macro invocation\n    |\n    = note: expected type `serde_closure::internal::a_variable`\n               found type `my_struct`\n```\n\n * Use of variables that start with an uppercase letter might need to be\n   disambiguated from types. If you see an error like the following, fix the\n   case of the variable, or wrap it with `(MyVariable)` to disambiguate.\n```text\nerror: imports cannot refer to local variables\n   --\u003e tests/test.rs:422:3\n    |\n417 |       FnOnce!(move || {\n    |  _____-\n418 | |         MyVariable;\n    | |         ^^^^^^^^^^\n419 | |     });\n    | |______- in this macro invocation\n    |\n```\n\n * Functions and closures called inside the closure might need to be\n   disambiguated. This can be done the same as above with `function::\u003c\u003e` for\n   functions and `(closure)` for closures.\n\n## Serializing between processes\n\nClosures created by this crate are unnameable – i.e. just like normal closures,\nthere is no Rust syntax available with which to write the type. What this means\nis that to deserialize a closure, you either need to specify the precise type\nyou're deserializing without naming it (which is possible but not particularly\npractical), or *erase* the type by storing it in a\n[trait object](https://doc.rust-lang.org/beta/book/ch17-02-trait-objects.html).\n\nThe [`serde_traitobject`](https://github.com/alecmocatta/serde_traitobject)\ncrate enables trait objects to be safely serialized and sent between other\nprocesses running the same binary.\n\nFor example, if you have multiple forks of a process, or the same binary running\non each of a cluster of machines,\n[`serde_traitobject`](https://github.com/alecmocatta/serde_traitobject) would\nhelp you to send serializable closures between them. This can be done by\nupcasting the closure to a `Box\u003cdyn serde_traitobject::Fn()\u003e`, which is\nautomatically serializable and deserializable with\n[`serde`](https://github.com/serde-rs/serde).\n\n## License\nLicensed under either of\n\n * Apache License, Version 2.0, ([LICENSE-APACHE.txt](LICENSE-APACHE.txt) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT.txt](LICENSE-MIT.txt) or http://opensource.org/licenses/MIT)\n\nat your option.\n\nUnless 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecmocatta%2Fserde_closure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falecmocatta%2Fserde_closure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecmocatta%2Fserde_closure/lists"}