• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/workflows/H03-May-2022-112101

ci/travis/H03-May-2022-10651

src/H03-May-2022-1,8501,574

tests/H03-May-2022-1,3311,021

.cargo-checksum.jsonH A D03-May-202289 11

.cargo_vcs_info.jsonH A D01-Jan-197074 65

.codecov.ymlH A D01-Jan-197035 43

.gitignoreH A D01-Jan-197033 43

.travis.ymlH A D01-Jan-1970536 4635

CHANGELOG.mdH A D01-Jan-19702.2 KiB8747

COPYINGH A D01-Jan-19701 KiB2217

Cargo.tomlH A D01-Jan-19702.1 KiB9477

Cargo.toml.orig-cargoH A D01-Jan-19701.5 KiB7163

README.mdH A D01-Jan-19706.6 KiB171131

README.md

1# �� `blanket` [![Star me](https://img.shields.io/github/stars/althonos/blanket.svg?style=social&label=Star&maxAge=3600)](https://github.com/althonos/blanket/stargazers)
2
3*A simple macro to derive blanket implementations for your traits.*
4
5[![Actions](https://img.shields.io/github/workflow/status/althonos/blanket/Test?style=flat-square&maxAge=600)](https://github.com/althonos/blanket/actions)
6[![Codecov](https://img.shields.io/codecov/c/gh/althonos/blanket/master.svg?style=flat-square&maxAge=600)](https://codecov.io/gh/althonos/blanket)
7[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square&maxAge=2678400)](https://choosealicense.com/licenses/mit/)
8[![Source](https://img.shields.io/badge/source-GitHub-303030.svg?maxAge=2678400&style=flat-square)](https://github.com/althonos/blanket)
9[![Crate](https://img.shields.io/crates/v/blanket.svg?maxAge=600&style=flat-square)](https://crates.io/crates/blanket)
10[![Documentation](https://img.shields.io/badge/docs.rs-latest-4d76ae.svg?maxAge=2678400&style=flat-square)](https://docs.rs/blanket)
11[![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)
12[![GitHub issues](https://img.shields.io/github/issues/althonos/blanket.svg?style=flat-square&maxAge=600)](https://github.com/althonos/blanket/issues)
13
14## �� Overview
15
16The Rust standard library has plenty of traits, but they shine in how well
17they integrate with new types. Declare an implementation of
18[`std::io::Write`] for
19a type `W`, and you also get it for [`&mut W`] and [`Box<W>`]! This however
20translates into a [lot of boilerplate code]
21that can be hard to maintain, which is why many crates don't bother
22providing the same convenience implementations.
23
24[`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
25[lot of boilerplate code]: https://doc.rust-lang.org/src/std/io/impls.rs.html#49-79
26[`&mut W`]: https://doc.rust-lang.org/std/io/trait.Write.html#impl-Write-17
27[`Box<W>`]: https://doc.rust-lang.org/std/io/trait.Write.html#impl-Write-19
28
29This is where `blanket` comes in! This crate helps you build the same kind
30of blanket implementations for your own traits with as least additional code
31as possible: in fact, this is as close as what a `derive` macro would look
32like for a `trait` item.
33
34## �� Usage
35
36`blanket` exports a single eponymous attribute macro, which can be imported
37simply after the crate has been added to the `Cargo.toml` dependencies:
38
39```rust
40extern crate blanket;
41use blanket::blanket;
42```
43
44### `#[blanket(derive(...))]`
45
46Use this macro attribute to derive a blanket implementation for a trait,
47provided the trait methods fit the constraints for that derive, such as
48only declaring methods with `&self` of `&mut self` as their receiver.
49The following derives are available:
50
51| Derive | Impl block                                 | `fn (&self)` | `fn (&mut self)` | `fn (self)` |
52|--------|--------------------------------------------|--------------|------------------|-------------|
53| Ref    | `impl<T: Trait + ?Sized> Trait for &T`     | ✔️            |                  |             |
54| Rc     | `impl<T: Trait + ?Sized> Trait for Rc<T>`  | ✔️            |                  |             |
55| Arc    | `impl<T: Trait + ?Sized> Trait for Arc<T>` | ✔️            |                  |             |
56| Mut    | `impl<T: Trait + ?Sized> Trait for &mut T` | ✔️            | ✔️                |             |
57| Box    | `impl<T: Trait> Trait for Box<T>`          | ✔️            | ✔️                | ✔️           |
58
59For instance, with our own version of `std::fmt::Write`, we can provide
60an implementation for `Box<impl Write>` and `&mut impl Write`:
61
62```rust
63extern crate blanket;
64use blanket::blanket;
65
66#[blanket(derive(Mut, Box))]
67pub trait Write {
68    fn write_str(&mut self, s: &str) -> std::fmt::Result;
69    fn write_char(&mut self, c: char) -> std::fmt::Result {
70         self.write_str(c.encode_utf8(&mut [0; 4]))
71    }
72}
73```
74
75Note that we can't derive `Ref` because the `Write` trait we declared expects
76mutable references, which we can't provide from an immutable reference. If we
77were to try, the compiler would warn us:
78
79```rustc
80---- src/lib.rs - (line 55) stdout ----
81error: cannot derive `Ref` for a trait declaring `&mut self` methods
82 --> src/lib.rs:61:18
83  |
848 |     fn write_str(&mut self, s: &str) -> std::fmt::Result;
85  |                  ^^^^^^^^^
86```
87
88
89### `#[blanket(default = "...")]`
90
91`blanket` can delegate default implementations of trait methods to functions
92of another module. This can be useful for some traits such as
93[visitors](https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md)
94to provide a default behaviour as an external function, such as what
95[`syn::visit`](https://docs.rs/syn/latest/syn/visit/index.html) is doing.
96
97The following example implements a very simple visitor trait for types
98able to process a `&str` char-by-char.
99
100```rust
101extern crate blanket;
102use blanket::blanket;
103
104#[blanket(default = "visitor")]
105trait Visitor {
106    fn visit_string(&self, s: &str);
107    fn visit_char(&self, c: char);
108}
109
110mod visitor {
111    use super::Visitor;
112
113    pub fn visit_string<V: Visitor + ?Sized>(v: &V, s: &str) {
114        for c in s.chars() {
115            v.visit_char(c);
116        }
117    }
118
119    pub fn visit_char<V: Visitor + ?Sized>(v: &V, c: char) {}
120}
121```
122
123`blanket` will check that all methods are declared without a default block,
124and then create a default implementation for all of the declared methods,
125generating the following code:
126
127```rust
128trait Visitor {
129    fn visit_string(&self, s: &str) {
130      visitor::visit_string(self, s)
131    }
132    fn visit_char(&self, c: char) {
133      visitor::visit_char(self, c)
134    }
135}
136```
137
138## �� To-Do
139
140- ✓ Delegation of default method to external functions.
141- ✓ Support for traits with generic arguments.
142- ✓ `#[derive(Ref)]`
143- ✓ `#[derive(Mut)]`
144- ✓ `#[derive(Box)]`
145- ✓ `#[derive(Rc)]`
146- ✓ `#[derive(Arc)]`
147- ✗ Update `Box` derive to allow unsized types if possible.
148- ✗ `#[derive(Cow)]`
149
150## �� Credits
151
152`blanket` is developed and maintained by:
153- [Martin Larralde](https://github.com/althonos)
154
155The following people contributed to the project:
156- [Alexander Linne](https://github.com/alexanderlinne)
157- [Naja Melan](https://github.com/najamelan)
158
159
160## �� Changelog
161
162This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
163and provides a [changelog](https://github.com/althonos/blanket/blob/master/CHANGELOG.md)
164in the [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) format.
165
166
167## �� License
168
169This library is provided under the open-source
170[MIT license](https://choosealicense.com/licenses/mit/).
171