#destruct #combinator #derive #self #simpler #metadata #destruct-type

destruct-derive

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

3个版本

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

#destruct中排名第6


2 crate中使用

MIT许可证

21KB
471

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 trait;
  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)] 以生成每个结构的impl。它等价于 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