use crate::environment::Environment;
use crate::error::BindError;
pub trait Binding<T> {
fn bind<E: Environment>(&self, environment: &E) -> Result<T, BindError>;
}
pub trait BindingExt: Sized {
#[must_use]
fn optional(self) -> OptionalVar<Self> {
OptionalVar { binding: self }
}
}
impl<B> BindingExt for B {}
pub struct OptionalVar<B> {
binding: B,
}
impl<T, B> Binding<Option<T>> for OptionalVar<B>
where
B: Binding<T>,
{
fn bind<E: Environment>(&self, environment: &E) -> Result<Option<T>, BindError> {
match self.binding.bind(environment) {
Ok(value) => Ok(Some(value)),
Err(BindError::MissingVariable { .. } | BindError::EmptyVariable { .. }) => Ok(None),
Err(error) => Err(error),
}
}
}
pub struct Binder<E>
where
E: Environment,
{
environment: E,
}
impl<E> Binder<E>
where
E: Environment,
{
#[must_use]
pub fn new(environment: E) -> Self {
Self { environment }
}
pub fn bind<T, B>(&self, binding: &B) -> Result<T, BindError>
where
B: Binding<T>,
{
binding.bind(&self.environment)
}
#[must_use]
pub fn environment(&self) -> &E {
&self.environment
}
}