premise 0.1.5

the core pattern library of Premise: sequences, tables, records, money, days and text, every function carrying the reason it exists
Documentation
use patterns_macros::because;

pub trait Context {
    type State;
    type Command;
    type Event;
    type Fault;

    fn initial() -> Self::State;
    fn decide(state: &Self::State, command: &Self::Command) -> Result<Self::Event, Self::Fault>;
    fn apply(state: Self::State, event: &Self::Event) -> Self::State;
}

pub fn replay_from<C: Context>(state: C::State, events: &[C::Event]) -> C::State {
    let mut next = state;
    for event in events {
        next = C::apply(next, event);
    }
    next
}

pub fn replay<C: Context>(events: &[C::Event]) -> C::State {
    replay_from::<C>(C::initial(), events)
}

pub fn handle<C: Context>(state: C::State, command: &C::Command) -> Result<C::State, C::Fault> {
    match C::decide(&state, command) {
        Ok(event) => Ok(C::apply(state, &event)),
        Err(fault) => Err(fault),
    }
}

pub fn handle_all<C: Context>(
    state: C::State,
    commands: &[C::Command],
) -> Result<C::State, (usize, C::Fault)> {
    let mut next = state;
    for (at, command) in commands.iter().enumerate() {
        match handle::<C>(next, command) {
            Ok(moved) => next = moved,
            Err(fault) => return Err((at, fault)),
        }
    }
    Ok(next)
}
because!(replay_from, "applying a run of events to a state that already exists, which is how replay works forward from initial and how a caller holding a snapshot catches up without folding the whole log again");
because!(replay, "folding a whole event log into the current state, so state is always derived and never stored");
because!(handle, "deciding on a command and applying the resulting event, so a caller cannot apply an event the rules did not produce");
because!(handle_all, "handle over a sequence, stopping at the first fault and naming the position of the command that raised it, because a partially applied batch is a state no replay can reach and a caller can only report or retry a batch when it knows where it broke");