use core::fmt::{Debug, Display};
pub mod builders;
use effectful::environment::{DynBind, EnvConfig, Environment, NativeForm};
use crate::protocol::{AsVisitor, DynVisitor};
/// A buildable type.
pub trait Build<'ctx, M, E: Environment>: Sized {
/// The builder that can be used to build a value of `Self`.
type Builder: Builder<'ctx, E, Value = Self>;
}
pub trait BuilderTypes<C: EnvConfig> {
type Seed: DynBind<C>;
/// Error that can happen during filling the builder with data.
type Error: DynBind<C> + Debug + Display;
type Output: DynBind<C>;
/// Type to be built.
type Value;
fn unwrap_output(output: Self::Output) -> Self::Value;
}
/// Builder for a type.
///
/// The `'ctx` lifetime is some lifetime that is longer than the walker.
/// As such, the built value can borrow from other data with a `'ctx` lifetimes.
///
/// A builder allows creating a value of a type [`Self::Value`][BuilderTypes::Value].
/// The way to use a builder is as follows.
/// - Call [`Default::default()`] to create an instance of the builder.
/// - Call [`Self::as_visitor()`] and give it to a walker's
/// [`walk()`][crate::walk::Walker::walk]. The walker will then fill
/// the builder with data from it's walk.
/// - Call [`Self::build()`] to finish building the value and get any errors
/// that happened during filling it with data.
pub trait Builder<'ctx, E: Environment>:
DynBind<E> + AsVisitor<'ctx, E> + BuilderTypes<E> + Sized
{
fn from_seed<'a>(seed: Self::Seed) -> NativeForm<'a, Self, E>
where
Self: 'a;
/// Finish the value.
///
/// If an error happened with the builder during the walk
/// it will be reported here.
fn build<'a>(self) -> NativeForm<'a, Result<Self::Output, Self::Error>, E>
where
Self: 'a;
}