8 个不稳定版本 (3 个重大更改)
0.4.0 | 2024 年 3 月 4 日 |
---|---|
0.3.0 | 2023 年 6 月 19 日 |
0.2.0 | 2021 年 6 月 5 日 |
0.1.5 | 2021 年 5 月 30 日 |
0.1.2 | 2020 年 7 月 23 日 |
#302 in Rust 模式
9,895 每月下载次数
用于 76 个crate (7 个直接使用)
86KB
2K SLoC
🧣 blanket
一个简单的宏,用于为您的特质生成泛型实现。
🔍 概述
Rust 标准库中有很多特质,但它们在与新类型集成方面的表现尤为出色。为类型 W
声明 std::io::Write
的实现,您也会得到 &mut W
和 Box<W>
的实现!然而,这会转化为大量的模板代码,难以维护,这也是为什么许多crate不愿意提供相同的便利实现。
这就是 blanket
的用武之地!这个crate帮助您用尽可能少的额外代码为自己的特质生成相同的泛型实现:事实上,这几乎与为 trait
项的 derive
宏看起来一样。
🔌 使用方法
blanket
导出一个同名的属性宏,在将crate添加到 Cargo.toml
依赖项之后可以简单地导入
extern crate blanket;
use blanket::blanket;
#[blanket(derive(...))]
使用此宏属性为特性行为生成一个通用的实现,前提是特性行为的方法符合该衍生约束,例如只声明具有&self
或&mut self
作为接收者的方法。以下是一些可用的衍生类型:
衍生类型 | 实现块 | fn (&self) |
fn (&mut self) |
fn (self) |
---|---|---|---|---|
Ref | impl<T:Trait+ ?Sized> Trait for &T |
✔️ | ||
Rc | impl<T:Trait+ ?Sized> Trait for Rc<T> |
✔️ | ||
Arc | impl<T:Trait+ ?Sized> Trait for Arc<T> |
✔️ | ||
Mut | impl<T:Trait+ ?Sized> Trait for &mut T |
✔️ | ✔️ | |
Box¹ | impl<T:Trait+ ?Sized> Trait for Box<T> |
✔️ | ✔️ | |
Box² | impl<T:Trait>Traitfor Box<T> |
✔️ | ✔️ | ✔️ |
Cow | impl<T:Trait+ ToOwned + ?Sized> Trait for Cow<_, T> |
✔️ |
例如,使用我们自己的版本std::fmt::Write
,我们可以为Box<impl Write>
和&mut impl Write
提供实现。
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]))
}
}
注意,我们无法推导出Ref
,因为我们声明的Write
特性行为期望可变引用,而我们从不可变引用中无法提供。如果我们尝试这样做,编译器会警告我们。
---- 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(默认值= "...")]
blanket
可以将特性行为的默认实现委托给另一个模块中的函数。这对于一些特性行为,如访问者,非常有用,可以提供一个作为外部函数的默认行为,例如syn::visit
所做的那样。
以下示例实现了一个非常简单的访问者特性行为,该行为可以逐字符处理类型为&str
的字符串。
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: Visitor + ?Sized>(v: &V, s: &str) {
for c in s.chars() {
v.visit_char(c);
}
}
pub fn visit_char<V: Visitor + ?Sized>(v: &V, c: char) {}
}
blanket
将检查所有方法是否声明时没有默认块,然后为所有声明的方法创建一个默认实现,生成以下代码:
trait Visitor {
fn visit_string(&self, s: &str) {
visitor::visit_string(self, s)
}
fn visit_char(&self, c: char) {
visitor::visit_char(self, c)
}
}
📝 待办事项
- ✓ 将默认方法委托给外部函数。
- ✓ 支持泛型参数的特性行为。
- ✓
#[derive(Ref)]
- ✓
#[derive(Mut)]
- ✓
#[derive(Box)]
支持有大小和无大小的类型。 - ✓
#[derive(Rc)]
- ✓
#[derive(Arc)]
- ✓
#[derive(Cow)]
🤝 致谢
blanket
由以下人员开发与维护:
以下人员对该项目做出了贡献
📋 变更日志
本项目遵循语义版本控制并提供变更日志,格式遵循保持变更日志。
📜 许可证
此库在开源MIT许可证下提供。
依赖项
~275–730KB
~17K SLoC