use super::CompilationError;
use super::Context;
use super::TxTmplIt;
use crate::contract::actions::ConditionallyCompileIfList;
use crate::contract::actions::GuardList;
use crate::template::Template;
use sapio_base::effects::EffectDBError;
use sapio_base::simp::ContinuationPointLT;
use sapio_base::simp::SIMPAttachableAt;
use sapio_base::Clause;
use serde_json::Value;
use core::marker::PhantomData;
use serde::Deserialize;
use std::sync::Arc;
pub struct FinishOrFunc<'a, ContractSelf, StatefulArguments, SpecificArgs, WebAPIStatus> {
pub simp_gen: Option<
fn(
&ContractSelf,
Context,
// TODO: Should this be able to observe all/any effects?
)
-> Result<Vec<Box<dyn SIMPAttachableAt<ContinuationPointLT>>>, CompilationError>,
>,
pub coerce_args: fn(StatefulArguments) -> Result<SpecificArgs, CompilationError>,
pub guard: GuardList<'a, ContractSelf>,
pub conditional_compile_if: ConditionallyCompileIfList<'a, ContractSelf>,
pub func: fn(&ContractSelf, Context, SpecificArgs) -> TxTmplIt,
pub schema: Option<Arc<Value>>,
pub name: Arc<String>,
pub f: PhantomData<WebAPIStatus>,
pub returned_txtmpls_modify_guards: bool,
pub extract_clause_from_txtmpl:
fn(&Template, &Context) -> Result<Option<Clause>, CompilationError>,
}
pub trait CallableAsFoF<ContractSelf, StatefulArguments> {
fn call(&self, cself: &ContractSelf, ctx: Context, o: StatefulArguments) -> TxTmplIt;
fn gen_simps(
&self,
cself: &ContractSelf,
ctx: Context,
) -> Result<Vec<Box<dyn SIMPAttachableAt<ContinuationPointLT>>>, CompilationError>;
fn call_json(&self, _cself: &ContractSelf, _ctx: Context, _o: serde_json::Value) -> TxTmplIt {
Err(CompilationError::WebAPIDisabled)
}
fn web_api(&self) -> bool {
false
}
fn get_conditional_compile_if(&self) -> ConditionallyCompileIfList<'_, ContractSelf>;
fn get_guard(&self) -> GuardList<'_, ContractSelf>;
fn get_name(&self) -> &Arc<String>;
fn get_schema(&self) -> &Option<Arc<Value>>;
fn get_returned_txtmpls_modify_guards(&self) -> bool;
fn get_extract_clause_from_txtmpl(
&self,
) -> fn(&Template, &Context) -> Result<Option<Clause>, CompilationError>;
fn rename(&mut self, a: Arc<String>);
}
pub struct WebAPIEnabled;
pub struct WebAPIDisabled;
impl<ContractSelf, StatefulArguments, SpecificArgs> CallableAsFoF<ContractSelf, StatefulArguments>
for FinishOrFunc<'_, ContractSelf, StatefulArguments, SpecificArgs, WebAPIDisabled>
{
fn call(&self, cself: &ContractSelf, ctx: Context, o: StatefulArguments) -> TxTmplIt {
let args = (self.coerce_args)(o)?;
(self.func)(cself, ctx, args)
}
fn get_conditional_compile_if(&self) -> ConditionallyCompileIfList<'_, ContractSelf> {
self.conditional_compile_if
}
fn get_guard(&self) -> GuardList<'_, ContractSelf> {
self.guard
}
fn get_name(&self) -> &Arc<String> {
&self.name
}
fn get_schema(&self) -> &Option<Arc<Value>> {
&self.schema
}
fn get_returned_txtmpls_modify_guards(&self) -> bool {
self.returned_txtmpls_modify_guards
}
fn get_extract_clause_from_txtmpl(
&self,
) -> fn(&Template, &Context) -> Result<Option<Clause>, CompilationError> {
self.extract_clause_from_txtmpl
}
fn rename(&mut self, a: Arc<String>) {
self.name = a;
}
fn gen_simps(
&self,
cself: &ContractSelf,
ctx: Context,
) -> Result<Vec<Box<dyn SIMPAttachableAt<ContinuationPointLT>>>, CompilationError> {
self.simp_gen.map(|f| (f)(cself, ctx)).unwrap_or(Ok(vec![]))
}
}
impl<ContractSelf, StatefulArguments, SpecificArgs> CallableAsFoF<ContractSelf, StatefulArguments>
for FinishOrFunc<'_, ContractSelf, StatefulArguments, SpecificArgs, WebAPIEnabled>
where
SpecificArgs: for<'de> Deserialize<'de>,
{
fn call(&self, cself: &ContractSelf, ctx: Context, o: StatefulArguments) -> TxTmplIt {
let args = (self.coerce_args)(o)?;
(self.func)(cself, ctx, args)
}
fn call_json(&self, cself: &ContractSelf, ctx: Context, o: serde_json::Value) -> TxTmplIt {
serde_json::from_value(o)
.map_err(EffectDBError::SerializationError)
.map_err(CompilationError::EffectDBError)
.and_then(|args| (self.func)(cself, ctx, args))
}
fn web_api(&self) -> bool {
true
}
fn get_conditional_compile_if(&self) -> ConditionallyCompileIfList<'_, ContractSelf> {
self.conditional_compile_if
}
fn get_guard(&self) -> GuardList<'_, ContractSelf> {
self.guard
}
fn get_name(&self) -> &Arc<String> {
&self.name
}
fn get_schema(&self) -> &Option<Arc<Value>> {
&self.schema
}
fn get_returned_txtmpls_modify_guards(&self) -> bool {
self.returned_txtmpls_modify_guards
}
fn get_extract_clause_from_txtmpl(
&self,
) -> fn(&Template, &Context) -> Result<Option<Clause>, CompilationError> {
self.extract_clause_from_txtmpl
}
fn rename(&mut self, a: Arc<String>) {
self.name = a;
}
fn gen_simps(
&self,
cself: &ContractSelf,
ctx: Context,
) -> Result<Vec<Box<dyn SIMPAttachableAt<ContinuationPointLT>>>, CompilationError> {
self.simp_gen.map(|f| (f)(cself, ctx)).unwrap_or(Ok(vec![]))
}
}
pub fn default_extract_clause_from_txtmpl(
t: &Template,
_ctx: &Context,
) -> Result<Option<Clause>, CompilationError> {
if !t.guards.is_empty() {
Err(CompilationError::AdditionalGuardsNotAllowedHere)
} else {
Ok(None)
}
}