use crate::{
form::MetaForm, tm_std::*, Field, MetaType, Path, Type, TypeDef, TypeDefComposite, TypeDefVariant, TypeInfo,
Variant,
};
pub mod state {
pub enum PathNotAssigned {}
pub enum PathAssigned {}
}
pub struct TypeBuilder<S = state::PathNotAssigned> {
path: Option<Path>,
type_params: Vec<MetaType>,
marker: PhantomData<fn() -> S>,
}
impl<S> Default for TypeBuilder<S> {
fn default() -> Self {
TypeBuilder {
path: Default::default(),
type_params: Default::default(),
marker: Default::default(),
}
}
}
impl TypeBuilder<state::PathNotAssigned> {
pub fn path(self, path: Path) -> TypeBuilder<state::PathAssigned> {
TypeBuilder {
path: Some(path),
type_params: self.type_params,
marker: Default::default(),
}
}
}
impl TypeBuilder<state::PathAssigned> {
fn build<D>(self, type_def: D) -> Type
where
D: Into<TypeDef>,
{
let path = self.path.expect("Path not assigned");
Type::new(path, self.type_params, type_def)
}
pub fn variant<V>(self, builder: VariantsBuilder<V>) -> Type {
self.build(builder.done())
}
pub fn composite<F>(self, fields: FieldsBuilder<F>) -> Type {
self.build(TypeDefComposite::new(fields.done()))
}
}
impl<S> TypeBuilder<S> {
pub fn type_params<I>(mut self, type_params: I) -> Self
where
I: IntoIterator<Item = MetaType>,
{
self.type_params = type_params.into_iter().collect();
self
}
}
pub enum NoFields {}
pub enum NamedFields {}
pub enum UnnamedFields {}
pub enum Fields {}
impl Fields {
pub fn unit() -> FieldsBuilder<NoFields> {
FieldsBuilder::<NoFields>::default()
}
pub fn named() -> FieldsBuilder<NamedFields> {
FieldsBuilder::default()
}
pub fn unnamed() -> FieldsBuilder<UnnamedFields> {
FieldsBuilder::default()
}
}
pub struct FieldsBuilder<T> {
fields: Vec<Field<MetaForm>>,
marker: PhantomData<fn() -> T>,
}
impl<T> Default for FieldsBuilder<T> {
fn default() -> Self {
Self {
fields: Vec::new(),
marker: Default::default(),
}
}
}
impl<T> FieldsBuilder<T> {
pub fn done(self) -> Vec<Field<MetaForm>> {
self.fields
}
}
impl FieldsBuilder<NamedFields> {
pub fn field(mut self, name: &'static str, ty: MetaType) -> Self {
self.fields.push(Field::named(name, ty));
self
}
pub fn field_of<T>(mut self, name: &'static str) -> Self
where
T: TypeInfo + ?Sized + 'static,
{
self.fields.push(Field::named_of::<T>(name));
self
}
}
impl FieldsBuilder<UnnamedFields> {
pub fn field(mut self, ty: MetaType) -> Self {
self.fields.push(Field::unnamed(ty));
self
}
pub fn field_of<T>(mut self) -> Self
where
T: TypeInfo + ?Sized + 'static,
{
self.fields.push(Field::unnamed_of::<T>());
self
}
}
pub enum NoVariants {}
pub enum VariantFields {}
pub enum Fieldless {}
pub enum Variants {}
impl Variants {
pub fn with_fields() -> VariantsBuilder<VariantFields> {
VariantsBuilder::new()
}
pub fn fieldless() -> VariantsBuilder<Fieldless> {
VariantsBuilder::new()
}
}
#[derive(Default)]
pub struct VariantsBuilder<T> {
variants: Vec<Variant>,
marker: PhantomData<fn() -> T>,
}
impl VariantsBuilder<VariantFields> {
pub fn variant<F>(mut self, name: &'static str, fields: FieldsBuilder<F>) -> Self {
self.variants.push(Variant::with_fields(name, fields));
self
}
pub fn variant_unit(self, name: &'static str) -> Self {
self.variant::<NoFields>(name, Fields::unit())
}
}
impl VariantsBuilder<Fieldless> {
pub fn variant(mut self, name: &'static str, discriminant: u64) -> Self {
self.variants.push(Variant::with_discriminant(name, discriminant));
self
}
}
impl<T> VariantsBuilder<T> {
fn new() -> Self {
VariantsBuilder {
variants: Vec::new(),
marker: Default::default(),
}
}
fn done(self) -> TypeDefVariant {
TypeDefVariant::new(self.variants)
}
}