#macro-derive #type #generate #enums #supertype #subtypes #supertypes

typesets

Enables generating subtypes and supertypes of a given type via derive macros

1 unstable release

0.0.2 Nov 28, 2021

#2995 in Rust patterns

Apache-2.0

4KB
58 lines

Typesets

This library aims to provide a set of macros that help remove the boilerplate of expressing relationships between different types.

Supertype

This derive macro provides the ability to generate enums which are a subset of the derived type.

To use, simply include the Supertype and denote which variants should go to which derived enums by the subtype attr.

#[derive(Supertype)]
pub enum MyExpansiveType {
  #[subtype(MyNarrowerType, MyOtherType)]
  State1(String),
  #[subtype(MyNarrowerType)]
  State2(u8),
  #[subtype(MyOtherType)]
  State3,
  State4
}

The above will expand to...

pub enum MyExpansiveType {
  State1(String),
  State2(u8),
  State3,
  State4
}

pub enum MyNarrowerType {
  State1(String),
  State2(u8)
}

impl TryFrom<MyExpansiveType> for MyNarrowerType {
  type Error = crate::TypesetsError;
  fn try_from(parent: MyExpansiveType) -> Result<Self, Self::Error> {
    match parent {
      MyExpansiveType::State1(v0) => Ok(MyNarrowerType::State1(v0)),
      MyExpansiveType::State2(v0) => Ok(MyNarrowerType::State2(v0)),
      other => Err(Self::Error::EnumNoOverlap {
        supertype: "MyExpansiveType",
        subtype: "MyNarrowerType",
        variant: format!("{:?}", other)
      })
    }
  }
}

impl From<MyNarrowerType> for MyExpansiveType {
  fn from(child: MyNarrowerType) -> Self {
    match child {
      MyNarrowerType::State1(v0) => MyExpansiveType::State1(v0),
      MyNarrowerType::State2(v0) => MyExpansiveType::State2(v0),
    }
  }
}

pub enum MyOtherType {
  State1(String),
  State3,
}


impl TryFrom<MyExpansiveType> for MyOtherType {
  type Error = crate::TypesetsError;
  fn try_from(parent: MyExpansiveType) -> Result<Self, Self::Error> {
    match parent {
      MyExpansiveType::State1(v0) => Ok(MyOtherType::State1(v0)),
      MyExpansiveType::State2(v0) => Ok(MyOtherType::State2(v0)),
      other => Err(Self::Error::EnumNoOverlap {
        supertype: "MyExpansiveType",
        subtype: "MyOtherType",
        variant: format!("{:?}", other)
      })
    }
  }
}

impl From<MyOtherType> for MyExpansiveType {
  fn from(child: MyOtherType) -> Self {
    match child {
      MyOtherType::State1(v0) => MyExpansiveType::State1(v0),
      MyOtherType::State2(v0) => MyExpansiveType::State2(v0),
    }
  }
}

Subtype

Sometimes you'll want to describe that a given enum is a subtype of another enum without actually having access to the original enum. This can be accomplished with the Subtype derive macro and the subtype_of attribute.

#[derive(Subtype)]
#[subtype_of(SomeSuperType)]
enum MySubType {
  Variant1,
  Variant2(u8)
}

which will expand to

enum MySubType {
  Variant1,
  Variant2(u8)
}

impl TryFrom<SomeSuperType> for MySubType {
  type Error = crate::typesets::subtype::SubtypeError;

  fn try_from(parent: SomeSuperType) -> Result<Self, Self::Error> {
    match parent {
      SomeSuperType::Variant1 => MySubType::Variant1,
      SomeSuperType::Variant2(v0) => MySubType::Variant2(v0),
      other => Self::Error::EnumNoOverlap {
        supertype: "SomeSuperType",
        subtype: "MySubType",
        variant: format!("{:?}", other)
      }
    }
  }
}

impl From<MySubType> for SomeSuperType {
  fn for(child: MySubType) -> Self {
    match child {
      MySubType::Variant1 => MySupertype::Variant1,
      MySubType::Variant2(v0) => MySupertype::Variant2(v0),
    }
  }
}

Dependencies

~0.5–1.2MB
~26K SLoC