use crate::function::FunctionBindings;
use crate::function::{Arguments, NonEmptyArguments, IntoFunction};
use crate::marker::*;
use crate::values::{IntoValue, StructValue, TypedValue};
use crate::variable::VariableBindings;
use crate::Error;
use std::marker::PhantomData;
pub trait ActivationInterface<'f, Fm: FnMarker = ()> {
fn variables(&self) -> &VariableBindings<'f>;
fn functions(&self) -> &FunctionBindings<'f>;
}
pub struct Activation<'f, Fm: FnMarker = ()> {
variables: VariableBindings<'f>,
functions: FunctionBindings<'f>,
_fn_marker: PhantomData<Fm>,
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub type AsyncActivation<'f> = Activation<'f, Async>;
impl<'f> Default for Activation<'f, ()> {
fn default() -> Self {
Self::new()
}
}
impl<'f> Activation<'f, ()> {
pub fn new() -> Self {
Self {
variables: VariableBindings::new(),
functions: FunctionBindings::new(),
_fn_marker: PhantomData,
}
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn force_async(self) -> Activation<'f, Async> {
Activation {
variables: self.variables,
functions: self.functions,
_fn_marker: PhantomData,
}
}
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
impl<'f> Activation<'f, Async> {
pub fn new_async() -> Self {
Self {
variables: VariableBindings::new(),
functions: FunctionBindings::new(),
_fn_marker: PhantomData,
}
}
}
impl<'f, Fm: FnMarker> Activation<'f, Fm> {
pub fn bind_variable<S, T>(mut self, name: S, value: T) -> Result<Self, Error>
where
S: Into<String>,
T: IntoValue + TypedValue,
{
self.variables.bind(name, value)?;
Ok(Activation {
variables: self.variables,
functions: self.functions,
_fn_marker: PhantomData,
})
}
pub fn bind_variable_dynamic<S>(
mut self,
name: S,
value: StructValue,
) -> Result<Self, Error>
where
S: Into<String>,
{
self.variables.bind_with_value(
name,
crate::ValueType::Struct(crate::types::StructType::new(value.type_name())),
value.into_value(),
)?;
Ok(Activation {
variables: self.variables,
functions: self.functions,
_fn_marker: PhantomData,
})
}
pub fn bind_variable_provider<S, F, Ffm>(
mut self,
name: S,
provider: F,
) -> Result<Activation<'f, <Ffm as FnMarkerAggr<Fm>>::Output>, Error>
where
S: Into<String>,
F: IntoFunction<'f, Ffm>,
Ffm: FnMarkerAggr<Fm>,
{
self.variables.bind_provider(name, provider)?;
Ok(Activation {
variables: self.variables,
functions: self.functions,
_fn_marker: PhantomData,
})
}
pub fn bind_function<S, F, Ffm, Args>(
mut self,
name: S,
member: bool,
f: F,
) -> Result<Activation<'f, <Ffm as FnMarkerAggr<Fm>>::Output>, Error>
where
S: Into<String>,
F: IntoFunction<'f, Ffm, Args>,
Ffm: FnMarkerAggr<Fm>,
Args: Arguments,
{
self.functions.bind(name, member, f)?;
Ok(Activation {
variables: self.variables,
functions: self.functions,
_fn_marker: PhantomData,
})
}
pub fn bind_member_function<S, F, Ffm, Args>(
self,
name: S,
f: F,
) -> Result<Activation<'f, <Ffm as FnMarkerAggr<Fm>>::Output>, Error>
where
S: Into<String>,
F: IntoFunction<'f, Ffm, Args>,
Ffm: FnMarkerAggr<Fm>,
Args: Arguments + NonEmptyArguments,
{
self.bind_function(name, true, f)
}
pub fn bind_global_function<S, F, Ffm, Args>(
self,
name: S,
f: F,
) -> Result<Activation<'f, <Ffm as FnMarkerAggr<Fm>>::Output>, Error>
where
S: Into<String>,
F: IntoFunction<'f, Ffm, Args>,
Ffm: FnMarkerAggr<Fm>,
Args: Arguments,
{
self.bind_function(name, false, f)
}
}
impl<'f, Fm: FnMarker> ActivationInterface<'f, Fm> for Activation<'f, Fm> {
fn variables(&self) -> &VariableBindings<'f> {
&self.variables
}
fn functions(&self) -> &FunctionBindings<'f> {
&self.functions
}
}
impl<'f, Fm: FnMarker> ActivationInterface<'f, Fm> for &Activation<'f, Fm> {
fn variables(&self) -> &VariableBindings<'f> {
(*self).variables()
}
fn functions(&self) -> &FunctionBindings<'f> {
(*self).functions()
}
}
impl<'f, Fm: FnMarker> ActivationInterface<'f, Fm> for std::sync::Arc<Activation<'f, Fm>> {
fn variables(&self) -> &VariableBindings<'f> {
(**self).variables()
}
fn functions(&self) -> &FunctionBindings<'f> {
(**self).functions()
}
}
impl<'f, Fm: FnMarker> ActivationInterface<'f, Fm> for Box<Activation<'f, Fm>> {
fn variables(&self) -> &VariableBindings<'f> {
(**self).variables()
}
fn functions(&self) -> &FunctionBindings<'f> {
(**self).functions()
}
}
static EMPTY_VARIABLES: std::sync::LazyLock<VariableBindings<'static>> =
std::sync::LazyLock::new(VariableBindings::new);
static EMPTY_FUNCTIONS: std::sync::LazyLock<FunctionBindings<'static>> =
std::sync::LazyLock::new(FunctionBindings::new);
impl ActivationInterface<'static> for () {
fn variables(&self) -> &VariableBindings<'static> {
&EMPTY_VARIABLES
}
fn functions(&self) -> &FunctionBindings<'static> {
&EMPTY_FUNCTIONS
}
}
impl ActivationInterface<'static> for &() {
fn variables(&self) -> &VariableBindings<'static> {
&EMPTY_VARIABLES
}
fn functions(&self) -> &FunctionBindings<'static> {
&EMPTY_FUNCTIONS
}
}
impl<'f, Fm: FnMarker> std::fmt::Debug for Activation<'f, Fm> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Activation")
.field("variables", &self.variables)
.field("functions", &self.functions)
.finish()
}
}