use crate::prelude::{
marker::PhantomData,
vec::Vec,
};
use crate::{
form::MetaForm,
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.finalize())
}
pub fn composite<F>(self, fields: FieldsBuilder<F>) -> Type {
self.build(TypeDefComposite::new(fields.finalize()))
}
}
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>,
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 finalize(self) -> Vec<Field<MetaForm>> {
self.fields
}
}
impl FieldsBuilder<NamedFields> {
pub fn field_of<T>(mut self, name: &'static str, type_name: &'static str) -> Self
where
T: TypeInfo + ?Sized + 'static,
{
self.fields.push(Field::named_of::<T>(name, type_name));
self
}
}
impl FieldsBuilder<UnnamedFields> {
pub fn field_of<T>(mut self, type_name: &'static str) -> Self
where
T: TypeInfo + ?Sized + 'static,
{
self.fields.push(Field::unnamed_of::<T>(type_name));
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 finalize(self) -> TypeDefVariant {
TypeDefVariant::new(self.variants)
}
}