Skip to content

Introduce extractor trait and patterns #33

@soareschen

Description

@soareschen

Summary

Following #32, a context-generic extractor pattern allows context-generic providers to pattern match on a generic context without access to the concrete context.

pub trait HasExtractor {
  type Extractor;

  fn extract(self) -> Self::Extractor;
}

pub trait CanExtractField<Tag, Value> {
  type Next;

  fn try_extract(self) -> Either<Value, Self::Next>;
}

pub trait DoneExtract {
  fn done_extract<T>(self) -> T;
}

pub struct Mismatch;

impl MapType for Mismatch {
  type Map<T> = Void;
}

Example

derive(Extractor)
pub enum Foo {
  Bar(u32),
  Baz(String),
}

would have the following derived:

pub enum FooExtractor<F1: MapType, F2: MapType> {
  Bar(F1::Map<u32>),
  Baz(F2::Map<String>),
}

impl<F2: MapType> CanExtract<symbol!("Bar"), u32> for FooExtractor<Filled, F2> {
  type Next = FooExtractor<Mismatch, F2>;

  fn try_extract(self) -> Either<u32, Self::Next> {
    match self {
      Self::Bar(value) => Either::Left(value),
      Self::Baz(value) => Either::Right(FooExtractor::Baz(value)),
    }
  }
}

impl<F1: MapType> CanExtract<symbol!("Baz"), String> for FooExtractor<F2, Filled> {
  type Next = FooExtractor<F2, Mismatch>;

  fn try_extract(self) -> Either<String, Self::Next> {
    match self {
      Self::Bar(value) => Either::Right(FooExtractor::Bar(value)),
      Self::Baz(value) => Either::Left(value),
    }
  }
}

impl DoneExtract for FooExtractor<Mismatch, Mismatch> {
  fn done_extract<T>(self) -> T {
    match self {
      Self::Bar(value) => match value {},
      Self::Baz(value) => match value {},
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions