batpak 0.7.0

Event sourcing with causal graphs and policy gates. Sync API, zero async.
Documentation
use crate::event::{EventKind, EventPayload};
use std::marker::PhantomData;

/// Private super-trait used to seal [`StateMarker`]. External crates cannot
/// add new [`StateMarker`] implementations because they cannot reach this
/// sealed trait — every library-generated state implements it via the
/// `define_state_machine!` macro (see `src/typestate/mod.rs`).
#[doc(hidden)]
pub mod sealed {
    /// Sealed marker implemented by every library-generated typestate.
    pub trait Sealed {}
}

/// Marker trait for states that may appear in typed transitions.
///
/// This trait is **sealed** via a private super-trait: only state types
/// generated by the library's typestate macros can implement it. External
/// crates that try to `impl StateMarker for MyType` will not compile because
/// they cannot reach `sealed::Sealed`.
pub trait StateMarker: sealed::Sealed {}

/// `Transition<From, To, P>`: a typed state change that carries an
/// [`EventPayload`] and therefore knows its [`EventKind`] structurally.
///
/// The payload type parameter `P: EventPayload` is the sole source of the
/// event kind; there is no constructor that takes an independent
/// [`EventKind`] argument, so a mismatched-kind storage is *structurally
/// impossible* rather than runtime-validated. See FREEZE-7 in the Integrity
/// Closeout II plan.
pub struct Transition<From: StateMarker, To: StateMarker, P: EventPayload> {
    payload: P,
    _from: PhantomData<From>,
    _to: PhantomData<To>,
}

impl<From: StateMarker, To: StateMarker, P: EventPayload> Transition<From, To, P> {
    /// Create a transition from a typed payload — kind derived from `P::KIND`.
    ///
    /// This is the **only** constructor for [`Transition`]. The event kind
    /// is read from [`EventPayload::KIND`] internally; callers cannot
    /// supply a kind that disagrees with the payload type.
    pub fn from_payload(payload: P) -> Self {
        Self {
            payload,
            _from: PhantomData,
            _to: PhantomData,
        }
    }

    /// Returns the [`EventKind`] this transition will persist under.
    ///
    /// Structurally equal to `P::KIND`; retained as a method for symmetry
    /// with `payload()` and for ergonomics at call sites.
    pub fn kind(&self) -> EventKind {
        P::KIND
    }

    /// Returns a reference to the transition payload.
    pub fn payload(&self) -> &P {
        &self.payload
    }

    /// Consumes the transition and returns the payload.
    pub fn into_payload(self) -> P {
        self.payload
    }
}