Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/althonos/blanket
A simple Rust macro to derive blanket implementations for your traits.
https://github.com/althonos/blanket
derive proc-macro-attributes rust-macro rust-trait
Last synced: 21 days ago
JSON representation
A simple Rust macro to derive blanket implementations for your traits.
- Host: GitHub
- URL: https://github.com/althonos/blanket
- Owner: althonos
- License: mit
- Created: 2020-07-21T02:04:18.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2024-03-04T11:51:44.000Z (9 months ago)
- Last Synced: 2024-10-20T21:03:05.577Z (27 days ago)
- Topics: derive, proc-macro-attributes, rust-macro, rust-trait
- Language: Rust
- Homepage: https://crates.io/crates/blanket
- Size: 133 KB
- Stars: 22
- Watchers: 3
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: COPYING
Awesome Lists containing this project
README
# ๐งฃ `blanket` [![Star me](https://img.shields.io/github/stars/althonos/blanket.svg?style=social&label=Star&maxAge=3600)](https://github.com/althonos/blanket/stargazers)
*A simple macro to derive blanket implementations for your traits.*
[![Actions](https://img.shields.io/github/actions/workflow/status/althonos/blanket/test.yml?branch=master&style=flat-square&maxAge=600)](https://github.com/althonos/blanket/actions)
[![Codecov](https://img.shields.io/codecov/c/gh/althonos/blanket/master.svg?style=flat-square&maxAge=600)](https://codecov.io/gh/althonos/blanket)
[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square&maxAge=2678400)](https://choosealicense.com/licenses/mit/)
[![Source](https://img.shields.io/badge/source-GitHub-303030.svg?maxAge=2678400&style=flat-square)](https://github.com/althonos/blanket)
[![Crate](https://img.shields.io/crates/v/blanket.svg?maxAge=600&style=flat-square)](https://crates.io/crates/blanket)
[![Documentation](https://img.shields.io/badge/docs.rs-latest-4d76ae.svg?maxAge=2678400&style=flat-square)](https://docs.rs/blanket)
[![Changelog](https://img.shields.io/badge/keep%20a-changelog-8A0707.svg?maxAge=2678400&style=flat-square)](https://github.com/althonos/blanket.rs/blob/master/CHANGELOG.md)
[![GitHub issues](https://img.shields.io/github/issues/althonos/blanket.svg?style=flat-square&maxAge=600)](https://github.com/althonos/blanket/issues)## ๐ Overview
The Rust standard library has plenty of traits, but they shine in how well
they integrate with new types. Declare an implementation of
[`std::io::Write`] for
a type `W`, and you also get it for [`&mut W`] and [`Box`]! This however
translates into a [lot of boilerplate code]
that can be hard to maintain, which is why many crates don't bother
providing the same convenience implementations.[`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
[lot of boilerplate code]: https://doc.rust-lang.org/src/std/io/impls.rs.html#49-79
[`&mut W`]: https://doc.rust-lang.org/std/io/trait.Write.html#impl-Write-17
[`Box`]: https://doc.rust-lang.org/std/io/trait.Write.html#impl-Write-19This is where `blanket` comes in! This crate helps you build the same kind
of blanket implementations for your own traits with as least additional code
as possible: in fact, this is as close as what a `derive` macro would look
like for a `trait` item.## ๐ Usage
`blanket` exports a single eponymous attribute macro, which can be imported
simply after the crate has been added to the `Cargo.toml` dependencies:```rust
extern crate blanket;
use blanket::blanket;
```### `#[blanket(derive(...))]`
Use this macro attribute to derive a blanket implementation for a trait,
provided the trait methods fit the constraints for that derive, such as
only declaring methods with `&self` of `&mut self` as their receiver.
The following derives are available:| Derive | Impl block | `fn (&self)` | `fn (&mut self)` | `fn (self)` |
|--------|---------------------------------------------------------|--------------|------------------|-------------|
| Ref | `impl Trait for &T` | โ๏ธ | | |
| Rc | `impl Trait for Rc` | โ๏ธ | | |
| Arc | `impl Trait for Arc` | โ๏ธ | | |
| Mut | `impl Trait for &mut T` | โ๏ธ | โ๏ธ | |
| Boxยน | `impl Trait for Box` | โ๏ธ | โ๏ธ | |
| Boxยฒ | `impl Trait for Box` | โ๏ธ | โ๏ธ | โ๏ธ |
| Cow | `impl Trait for Cow<_, T>` | โ๏ธ | | |For instance, with our own version of `std::fmt::Write`, we can provide
an implementation for `Box` and `&mut impl Write`:```rust
extern crate blanket;
use blanket::blanket;#[blanket(derive(Mut, Box))]
pub trait Write {
fn write_str(&mut self, s: &str) -> std::fmt::Result;
fn write_char(&mut self, c: char) -> std::fmt::Result {
self.write_str(c.encode_utf8(&mut [0; 4]))
}
}
```Note that we can't derive `Ref` because the `Write` trait we declared expects
mutable references, which we can't provide from an immutable reference. If we
were to try, the compiler would warn us:```rustc
---- src/lib.rs - (line 55) stdout ----
error: cannot derive `Ref` for a trait declaring `&mut self` methods
--> src/lib.rs:61:18
|
8 | fn write_str(&mut self, s: &str) -> std::fmt::Result;
| ^^^^^^^^^
```### `#[blanket(default = "...")]`
`blanket` can delegate default implementations of trait methods to functions
of another module. This can be useful for some traits such as
[visitors](https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md)
to provide a default behaviour as an external function, such as what
[`syn::visit`](https://docs.rs/syn/latest/syn/visit/index.html) is doing.The following example implements a very simple visitor trait for types
able to process a `&str` char-by-char.```rust,ignore
extern crate blanket;
use blanket::blanket;#[blanket(default = "visitor")]
trait Visitor {
fn visit_string(&self, s: &str);
fn visit_char(&self, c: char);
}mod visitor {
use super::Visitor;pub fn visit_string(v: &V, s: &str) {
for c in s.chars() {
v.visit_char(c);
}
}pub fn visit_char(v: &V, c: char) {}
}
````blanket` will check that all methods are declared without a default block,
and then create a default implementation for all of the declared methods,
generating the following code:```rust,ignore
trait Visitor {
fn visit_string(&self, s: &str) {
visitor::visit_string(self, s)
}
fn visit_char(&self, c: char) {
visitor::visit_char(self, c)
}
}
```## ๐ To-Do
- โ Delegation of default method to external functions.
- โ Support for traits with generic arguments.
- โ `#[derive(Ref)]`
- โ `#[derive(Mut)]`
- โ `#[derive(Box)]` for both sized and unsized types.
- โ `#[derive(Rc)]`
- โ `#[derive(Arc)]`
- โ `#[derive(Cow)]`## ๐ค Credits
`blanket` is developed and maintained by:
- [Martin Larralde](https://github.com/althonos)The following people contributed to the project:
- [Alexander Linne](https://github.com/alexanderlinne)
- [Naja Melan](https://github.com/najamelan)
- [Justin Lovinger](https://github.com/JustinLovinger)## ๐ Changelog
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
and provides a [changelog](https://github.com/althonos/blanket/blob/master/CHANGELOG.md)
in the [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) format.## ๐ License
This library is provided under the open-source
[MIT license](https://choosealicense.com/licenses/mit/).