type_utils 0.3.0

Generate types based on existing types
Documentation
use proc_macro::TokenStream;
use proc_macro2::Ident;
use quote::ToTokens;
use std::fmt::{Display, Formatter};
use syn::{
  parse_macro_input, Attribute, FieldsNamed, FieldsUnnamed, Generics, Variant, Visibility,
};

mod parse_impl;
mod to_tokens_impl;

#[proc_macro_derive(TypeUtils, attributes(tu_derive, pick, omit))]
pub fn type_utils(input: TokenStream) -> TokenStream {
  parse_macro_input!(input as TypeUtils)
    .into_token_stream()
    .into()
}

#[derive(Clone)]
struct TypeUtils {
  kind: TypeKind,
  attrs: Vec<Attribute>,
  actions: Vec<Action>,
  ident: Ident,
}

#[derive(Clone)]
struct Action {
  kind: ActionKind,
  derives: Vec<Ident>,
  vis: Visibility,
  ident: Ident,
  generics: Generics,
  selection: Selection,
}

#[derive(Copy, Clone)]
enum ActionKind {
  Pick,
  Omit,
}

impl Display for ActionKind {
  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
    match self {
      ActionKind::Pick => write!(f, "pick"),
      ActionKind::Omit => write!(f, "omit"),
    }
  }
}

#[derive(Clone)]
struct Selection(Vec<SelectedField>);

#[derive(Clone)]
struct SelectedField {
  vis: Visibility,
  ident: Ident,
}

#[derive(Clone)]
enum TypeKind {
  Struct(FieldsNamed),
  TupleStruct(FieldsUnnamed),
  UnitStruct,
  Enum(Vec<Variant>),
}

impl TypeKind {
  fn display(&self) -> &'static str {
    match self {
      TypeKind::Struct(_) => "struct",
      TypeKind::TupleStruct(_) => "tuple struct",
      TypeKind::UnitStruct => "unit struct",
      TypeKind::Enum(_) => "enum",
    }
  }
}