Skip to main content

ferro_projections/
error.rs

1use thiserror::Error;
2
3#[derive(Error, Debug)]
4pub enum Error {
5    #[error("service definition error: {0}")]
6    Definition(String),
7    #[error("validation error: {0}")]
8    Validation(String),
9    #[error("render error: {0}")]
10    Render(String),
11    #[error("serialization error: {0}")]
12    Serialization(#[from] serde_json::Error),
13    /// Caller supplied an empty intents slice — no render target exists.
14    /// Returned by render entry points instead of a silent `"unknown"`;
15    /// defined here so non-visual renderers can consume it. (D-08)
16    #[error("cannot render service with no intents")]
17    NoIntents,
18    /// An action selected for transition derivation declares no
19    /// `transition_trigger`, so no event-to-target mapping exists.
20    #[error("action '{0}' has no transition_trigger")]
21    NoTransitionTrigger(String),
22    /// Transition derivation was requested for a service with no state machine.
23    #[error("service '{0}' has no state machine")]
24    NoStateMachine(String),
25    /// An action's `transition_trigger` names an event that no declared
26    /// transition carries — the EXEC-04 drift condition, by construction.
27    #[error("action '{action}' transition_trigger '{event}' matches no declared transition")]
28    UndeclaredTransition { action: String, event: String },
29    /// A single event fans out to more than one target state across its
30    /// transitions; a `TransitionPlan` cannot pick one unambiguously.
31    #[error("event '{event}' fans out to multiple target states — ambiguous transition plan")]
32    AmbiguousTransition { event: String },
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn no_intents_error_message() {
41        let err = Error::NoIntents;
42        assert_eq!(err.to_string(), "cannot render service with no intents");
43    }
44}