1 个不稳定版本
0.0.1 | 2022 年 11 月 23 日 |
---|
#38 in #deriving
17KB
EnumConversions
一个派生枚举上自然 From
/ TryFrom
特质的 crate。它提供的主要宏有 #[EnumConversions]
和 #[DeriveTryFrom]
。
这个 crate 意在替代 variant_access crate。它尝试使用更常见的 TryFrom
特质而不是 crate 本地的特质(尽管这并不总是可能的,见下文)。它还去除了枚举中的类型必须是 'static
的需求,并且不会为定义可能变得模糊的泛型类型编译(variant_access
会编译但可能不会提供预期的行为)。
用法
给定一个枚举
#[EnumConversions]
#[DeriveTryFrom]
enum Enum {
F1(i32),
F2(bool),
}
将实现由本 crate 提供的 TryTo
特质以及枚举中每个变体的 TryFrom
特质。它还会派生反方向的 From
特质。如果没有 #[DeriveTryFrom]
,则默认情况下不会派生 TryFrom
特质。
如果只想在枚举的某些变体上派生 TryFrom
特质,则可以分别标记
#[EnumConversions]
enum Enum<U> {
F1(RefCell<U>),
#[DeriveTryFrom]
F2(bool),
}
此外,可以通过传递所需的错误类型和一个闭包将 EnumConversionError
映射到该错误类型来配置 TryTo /
TryFrom
特质的错误,如下所示
use std::error::Error;
#[EnumConvesions(
Error: Box<dyn Error + 'static>,
|e| e.to_string().into()
)]
enum Enum<U> {
F1(RefCell<U>),
#[DeriveTryFrom]
F2(bool),
}
限制和注意事项
这些应该由宏验证,或者会导致编译器错误。对于前者,它们可以在 enum-conversion-derive
内的单元测试中找到。后者可以在 /tests
的 uncompilable_examples
子目录中找到。
枚举变体必须包含无歧义的类型。
以下类型的枚举变体在每个变体中都没有无歧义的类型
enum Enum {
NamedFields{a: bool, b: i32},
UnnamedField(bool, i32),
Unit,
}
如果这些中的任何一个存在于枚举中,则宏将引发恐慌。
任何类型都不能出现在多个变体中。
无法推导出 TryFrom<Enum> for bool
,其中
enum Enum {
F1(bool),
F2(bool),
}
应该选择第一个或第二个变体?如果一个类型不能明确地对应到单个字段,宏将会崩溃,或者Rust编译器会报出存在多个实现。
这种现象的更复杂例子是
enum Enum<'a, 'b, U, T> {
Ref1(&'a U),
Ref2(&'b T),
}
任何对TryFrom
特质的泛型实现也应在特化的类型 Enum<'a, 'a, bool, bool>
上工作,这是由于上述原因。在这种情况下,宏不会崩溃,但编译器会指出存在多个实现并报错。
在外国类型上实现外国特质。
Rust 对孤儿特质实现有严格的规则,见 错误代码 E0210。
特别是,不允许在外国类型上实现外国特质。由于 TryFrom
是一个外国特质,所以不能像这样为泛型参数推导它
#[EnumConversion]
#[DeriveTryFrom]
enum Enum<U> {
F1(RefCell<U>),
F2(bool),
}
这就是为什么 TryFrom
默认不实现,并且为什么它可以全局或仅对特定变体进行推导。而 TryTo
特质不是外国特质,可以用作 TryInto
的替代品。
依赖项
~8–18MB
~231K SLoC