#combinator #structs #simpler #metadata

destruct

简化组合库实现的销毁结构体和枚举

3 个版本

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

#1249Rust 模式

MIT 许可证

16KB
272

销毁

将结构体和枚举销毁成一个包含一组固定类型的异构列表,以便快速实现组合库。

API

特质 销毁

类型 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-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)] 生成每个结构体的 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