{"id":16916924,"url":"https://github.com/althonos/blanket","last_synced_at":"2025-09-07T17:31:34.959Z","repository":{"id":50052950,"uuid":"281270886","full_name":"althonos/blanket","owner":"althonos","description":"A simple Rust macro to derive blanket implementations for your traits.","archived":false,"fork":false,"pushed_at":"2024-03-04T11:51:44.000Z","size":136,"stargazers_count":22,"open_issues_count":3,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-28T01:16:01.003Z","etag":null,"topics":["derive","proc-macro-attributes","rust-macro","rust-trait"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/blanket","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/althonos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-21T02:04:18.000Z","updated_at":"2024-10-18T02:33:21.000Z","dependencies_parsed_at":"2024-01-16T18:56:32.587Z","dependency_job_id":"957c9118-a40f-4b38-a2be-ca38ffa2fafb","html_url":"https://github.com/althonos/blanket","commit_stats":{"total_commits":87,"total_committers":5,"mean_commits":17.4,"dds":"0.48275862068965514","last_synced_commit":"ce0b8ab848769680d2f290bf1d000c2dbbb29d8a"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/althonos%2Fblanket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/althonos%2Fblanket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/althonos%2Fblanket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/althonos%2Fblanket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/althonos","download_url":"https://codeload.github.com/althonos/blanket/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232233620,"owners_count":18492613,"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":["derive","proc-macro-attributes","rust-macro","rust-trait"],"created_at":"2024-10-13T19:31:24.904Z","updated_at":"2025-01-02T17:43:55.554Z","avatar_url":"https://github.com/althonos.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🧣 `blanket` [![Star me](https://img.shields.io/github/stars/althonos/blanket.svg?style=social\u0026label=Star\u0026maxAge=3600)](https://github.com/althonos/blanket/stargazers)\n\n*A simple macro to derive blanket implementations for your traits.*\n\n[![Actions](https://img.shields.io/github/actions/workflow/status/althonos/blanket/test.yml?branch=master\u0026style=flat-square\u0026maxAge=600)](https://github.com/althonos/blanket/actions)\n[![Codecov](https://img.shields.io/codecov/c/gh/althonos/blanket/master.svg?style=flat-square\u0026maxAge=600)](https://codecov.io/gh/althonos/blanket)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square\u0026maxAge=2678400)](https://choosealicense.com/licenses/mit/)\n[![Source](https://img.shields.io/badge/source-GitHub-303030.svg?maxAge=2678400\u0026style=flat-square)](https://github.com/althonos/blanket)\n[![Crate](https://img.shields.io/crates/v/blanket.svg?maxAge=600\u0026style=flat-square)](https://crates.io/crates/blanket)\n[![Documentation](https://img.shields.io/badge/docs.rs-latest-4d76ae.svg?maxAge=2678400\u0026style=flat-square)](https://docs.rs/blanket)\n[![Changelog](https://img.shields.io/badge/keep%20a-changelog-8A0707.svg?maxAge=2678400\u0026style=flat-square)](https://github.com/althonos/blanket.rs/blob/master/CHANGELOG.md)\n[![GitHub issues](https://img.shields.io/github/issues/althonos/blanket.svg?style=flat-square\u0026maxAge=600)](https://github.com/althonos/blanket/issues)\n\n## 🔍 Overview\n\nThe Rust standard library has plenty of traits, but they shine in how well\nthey integrate with new types. Declare an implementation of\n[`std::io::Write`] for\na type `W`, and you also get it for [`\u0026mut W`] and [`Box\u003cW\u003e`]! This however\ntranslates into a [lot of boilerplate code]\nthat can be hard to maintain, which is why many crates don't bother\nproviding the same convenience implementations.\n\n[`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html\n[lot of boilerplate code]: https://doc.rust-lang.org/src/std/io/impls.rs.html#49-79\n[`\u0026mut W`]: https://doc.rust-lang.org/std/io/trait.Write.html#impl-Write-17\n[`Box\u003cW\u003e`]: https://doc.rust-lang.org/std/io/trait.Write.html#impl-Write-19\n\nThis is where `blanket` comes in! This crate helps you build the same kind\nof blanket implementations for your own traits with as least additional code\nas possible: in fact, this is as close as what a `derive` macro would look\nlike for a `trait` item.\n\n## 🔌 Usage\n\n`blanket` exports a single eponymous attribute macro, which can be imported\nsimply after the crate has been added to the `Cargo.toml` dependencies:\n\n```rust\nextern crate blanket;\nuse blanket::blanket;\n```\n\n### `#[blanket(derive(...))]`\n\nUse this macro attribute to derive a blanket implementation for a trait,\nprovided the trait methods fit the constraints for that derive, such as\nonly declaring methods with `\u0026self` of `\u0026mut self` as their receiver.\nThe following derives are available:\n\n| Derive | Impl block                                              | `fn (\u0026self)` | `fn (\u0026mut self)` | `fn (self)` |\n|--------|---------------------------------------------------------|--------------|------------------|-------------|\n| Ref    | `impl\u003cT: Trait + ?Sized\u003e Trait for \u0026T`                  | ✔️            |                  |             |\n| Rc     | `impl\u003cT: Trait + ?Sized\u003e Trait for Rc\u003cT\u003e`               | ✔️            |                  |             |\n| Arc    | `impl\u003cT: Trait + ?Sized\u003e Trait for Arc\u003cT\u003e`              | ✔️            |                  |             |\n| Mut    | `impl\u003cT: Trait + ?Sized\u003e Trait for \u0026mut T`              | ✔️            | ✔️                |             |\n| Box¹   | `impl\u003cT: Trait + ?Sized\u003e Trait for Box\u003cT\u003e`              | ✔️            | ✔️                |             |\n| Box²   | `impl\u003cT: Trait\u003e Trait for Box\u003cT\u003e`                       | ✔️            | ✔️                | ✔️           |\n| Cow    | `impl\u003cT: Trait + ToOwned + ?Sized\u003e Trait for Cow\u003c_, T\u003e` | ✔️            |                  |             |\n\nFor instance, with our own version of `std::fmt::Write`, we can provide\nan implementation for `Box\u003cimpl Write\u003e` and `\u0026mut impl Write`:\n\n```rust\nextern crate blanket;\nuse blanket::blanket;\n\n#[blanket(derive(Mut, Box))]\npub trait Write {\n    fn write_str(\u0026mut self, s: \u0026str) -\u003e std::fmt::Result;\n    fn write_char(\u0026mut self, c: char) -\u003e std::fmt::Result {\n         self.write_str(c.encode_utf8(\u0026mut [0; 4]))\n    }\n}\n```\n\nNote that we can't derive `Ref` because the `Write` trait we declared expects\nmutable references, which we can't provide from an immutable reference. If we\nwere to try, the compiler would warn us:\n\n```rustc\n---- src/lib.rs - (line 55) stdout ----\nerror: cannot derive `Ref` for a trait declaring `\u0026mut self` methods\n --\u003e src/lib.rs:61:18\n  |\n8 |     fn write_str(\u0026mut self, s: \u0026str) -\u003e std::fmt::Result;\n  |                  ^^^^^^^^^\n```\n\n\n### `#[blanket(default = \"...\")]`\n\n`blanket` can delegate default implementations of trait methods to functions\nof another module. This can be useful for some traits such as\n[visitors](https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md)\nto provide a default behaviour as an external function, such as what\n[`syn::visit`](https://docs.rs/syn/latest/syn/visit/index.html) is doing.\n\nThe following example implements a very simple visitor trait for types\nable to process a `\u0026str` char-by-char.\n\n```rust,ignore\nextern crate blanket;\nuse blanket::blanket;\n\n#[blanket(default = \"visitor\")]\ntrait Visitor {\n    fn visit_string(\u0026self, s: \u0026str);\n    fn visit_char(\u0026self, c: char);\n}\n\nmod visitor {\n    use super::Visitor;\n\n    pub fn visit_string\u003cV: Visitor + ?Sized\u003e(v: \u0026V, s: \u0026str) {\n        for c in s.chars() {\n            v.visit_char(c);\n        }\n    }\n\n    pub fn visit_char\u003cV: Visitor + ?Sized\u003e(v: \u0026V, c: char) {}\n}\n```\n\n`blanket` will check that all methods are declared without a default block,\nand then create a default implementation for all of the declared methods,\ngenerating the following code:\n\n```rust,ignore\ntrait Visitor {\n    fn visit_string(\u0026self, s: \u0026str) {\n      visitor::visit_string(self, s)\n    }\n    fn visit_char(\u0026self, c: char) {\n      visitor::visit_char(self, c)\n    }\n}\n```\n\n## 📝 To-Do\n\n- ✓ Delegation of default method to external functions.\n- ✓ Support for traits with generic arguments.\n- ✓ `#[derive(Ref)]`\n- ✓ `#[derive(Mut)]`\n- ✓ `#[derive(Box)]` for both sized and unsized types.\n- ✓ `#[derive(Rc)]`\n- ✓ `#[derive(Arc)]`\n- ✓ `#[derive(Cow)]`\n\n## 🤝 Credits\n\n`blanket` is developed and maintained by:\n- [Martin Larralde](https://github.com/althonos)\n\nThe following people contributed to the project:\n- [Alexander Linne](https://github.com/alexanderlinne)\n- [Naja Melan](https://github.com/najamelan)\n- [Justin Lovinger](https://github.com/JustinLovinger)\n\n## 📋 Changelog\n\nThis project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)\nand provides a [changelog](https://github.com/althonos/blanket/blob/master/CHANGELOG.md)\nin the [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) format.\n\n\n## 📜 License\n\nThis library is provided under the open-source\n[MIT license](https://choosealicense.com/licenses/mit/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falthonos%2Fblanket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falthonos%2Fblanket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falthonos%2Fblanket/lists"}