3 个版本
0.1.2 | 2019年11月7日 |
---|---|
0.1.1 | 2019年10月15日 |
0.1.0 | 2019年10月15日 |
#182 in 解析工具
用于 destruct
11KB
268 行
Destruct
将 Destruct 结构体和枚举解构为包含一组固定类型的异构列表,以实现组合器库的快速实现。
API
trait Destruct
type DestructType
解构对象类型
如果你的结构体是
#[derive(Destruct)]
struct YourStruct {
field: YourField,
field2: YourField2,
}
那么 DestructType 是
DestructBegin<Fields, m>
where Fields = DestructField<YourField, NextField, m1>
NextField = DestructField<YourField2, End, m2>
End = DestructEnd<m>
where m is some generated type implementing `trait DestructMetadata`
m1 is the metadata for `field`, implementing `trait DestructFieldMetadata + DestructMetadata`
m2 is the metadata for `field2`, implementing `trait DestructFieldMetadata + DestructMetadata`
}
以下是在 DestructType 中可能出现的类型列表
- DestructBegin
- DestructField
- DestructEnd
- DestructEnumBegin
- DestructEnumVariant
- DestructEnumEnd
fn destruct(self) -> Self::DestructType
将 self 解构为解构类型
fn construct(d: Self::DestructType) -> Self;
从解构类型构造 self
元数据
pub trait DestructMetadata {
fn struct_name() -> &'static str;
fn named_fields() -> bool;
}
pub trait DestructFieldMetadata: DestructMetadata + 'static {
fn field_name() -> &'static str;
fn field_index() -> usize;
}
pub trait DestructEnumMetadata {
fn enum_name() -> &'static str;
}
pub trait DestructEnumVariantMetadata: DestructEnumMetadata + 'static {
fn variant_name() -> &'static str;
fn variant_index() -> usize;
}
示例
例如,以下是使用 destruct 实现解析器的方式(参见 destruct-parser
)
- 编写一个
Parsable
特性; - 实现基本类型的解析器;
- 实现六个 Destruct 类型的解析器;
- 通过添加
#[derive(Destruct)]
为您的结构体派生Destruct
; - (可选) 实现一个用于派生
impl<T: Destruct> Parsable
的宏,即parsable!
; - (可选) 通过添加
#[destruct(parsable)]
为您的结构体实现Parsable
;
为什么我需要 parsable!
宏?
因为 Rust 禁止重叠实现特性。理想情况下,我需要以下特性实现
impl<T: Destruct> Parsable for T where T::DestructType: Parsable {}
但 Rust 抱怨
upstream crates may add new impl of trait `destruct::Destruct` for type `destruct::DestructEnumBegin<_, _>` in future versions
因此,我添加了 #[destruct(parsable)]
来为每个结构体生成实现。它等价于 parsable!(YourStruct)
。
#[macro_export]
macro_rules! parsable {
($t:ident) => {
impl Parsable for $t {
fn parse<R: io::Read + Clone>(read: &mut R) -> Result<Self, Error> {
<$t as Destruct>::DestructType::parse(read).map(<$t as Destruct>::construct)
}
}
};
}
局限性
不支持泛型。
依赖项
约1.5MB
约35K SLoC