#destruct #combinator #parser #construct #self #simpler #metadata

destruct-lib

简化组合器实现的 Destruct 结构体和枚举

3 个版本

0.1.2 2019年11月7日
0.1.1 2019年10月15日
0.1.0 2019年10月15日

#182 in 解析工具


用于 destruct

MIT 许可证

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

  1. 编写一个 Parsable 特性;
  2. 实现基本类型的解析器;
  3. 实现六个 Destruct 类型的解析器;
  4. 通过添加 #[derive(Destruct)] 为您的结构体派生 Destruct
  5. (可选) 实现一个用于派生 impl<T: Destruct> Parsable 的宏,即 parsable!
  6. (可选) 通过添加 #[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