use trellis_core::{GraphResult, InputNode, Transaction};
pub(crate) type StageOperation<C, O> =
dyn for<'tx> Fn(&mut Transaction<'tx, C, O>) -> GraphResult<()> + 'static;
pub struct TransactionScript<C = (), O = ()> {
pub(crate) steps: Vec<TransactionScriptStep<C, O>>,
}
impl<C, O> TransactionScript<C, O> {
pub fn new() -> Self {
Self { steps: Vec::new() }
}
pub fn step(&mut self, name: impl Into<String>) -> TransactionScriptStepBuilder<'_, C, O> {
TransactionScriptStepBuilder {
script: self,
name: name.into(),
operations: Vec::new(),
}
}
pub fn steps(&self) -> &[TransactionScriptStep<C, O>] {
&self.steps
}
}
impl<C, O> Default for TransactionScript<C, O> {
fn default() -> Self {
Self::new()
}
}
pub struct TransactionScriptStepBuilder<'script, C, O> {
script: &'script mut TransactionScript<C, O>,
name: String,
operations: Vec<Box<StageOperation<C, O>>>,
}
impl<C, O> TransactionScriptStepBuilder<'_, C, O>
where
O: Clone + PartialEq,
{
pub fn input<T>(mut self, input: InputNode<T>, value: T) -> Self
where
T: Clone + PartialEq + Send + Sync + 'static,
{
self.operations
.push(Box::new(move |tx| tx.set_input(input, value.clone())));
self
}
pub fn operation(
mut self,
operation: impl for<'tx> Fn(&mut Transaction<'tx, C, O>) -> GraphResult<()> + 'static,
) -> Self {
self.operations.push(Box::new(operation));
self
}
pub fn commit(self) {
self.script.steps.push(TransactionScriptStep {
name: self.name,
operations: self.operations,
});
}
}
pub struct TransactionScriptStep<C = (), O = ()> {
pub(crate) name: String,
pub(crate) operations: Vec<Box<StageOperation<C, O>>>,
}
impl<C, O> TransactionScriptStep<C, O> {
pub fn name(&self) -> &str {
&self.name
}
}