Skip to main content

sim_lib_music_serial/
error.rs

1//! Typed serial-plan validation failures.
2
3use thiserror::Error;
4
5use crate::{OrdinalRef, RowInstanceId, SerialEventId, SimultaneousGroupId, StructuralReadingId};
6
7/// Failure while validating immutable serial-plan data.
8#[derive(Clone, Debug, PartialEq, Eq, Error)]
9pub enum SerialPlanError {
10    /// A stable identifier was empty or used an unsafe character.
11    #[error("invalid {kind} id {value:?}: {reason}")]
12    InvalidId {
13        /// Identity kind being validated.
14        kind: &'static str,
15        /// Rejected text.
16        value: String,
17        /// Specific syntax failure.
18        reason: &'static str,
19    },
20    /// A planned event referenced a missing row instance.
21    #[error("event {event_id} references unknown row {row_id}")]
22    UnknownRow {
23        /// Planned event carrying the bad reference.
24        event_id: SerialEventId,
25        /// Referenced row id.
26        row_id: RowInstanceId,
27    },
28    /// A planned event referenced an ordinal outside the source row.
29    #[error(
30        "event {event_id} references ordinal {ordinal} outside row {row_id} with length {row_len}"
31    )]
32    OrdinalOutOfRange {
33        /// Planned event carrying the bad reference.
34        event_id: SerialEventId,
35        /// Referenced row instance.
36        row_id: RowInstanceId,
37        /// Rejected ordinal.
38        ordinal: usize,
39        /// Row length expected by the referenced row form.
40        row_len: usize,
41    },
42    /// The same structural role rules were violated.
43    #[error("event {event_id} has role/origin mismatch: {reason}")]
44    RoleOriginMismatch {
45        /// Affected event.
46        event_id: SerialEventId,
47        /// Human-readable validation reason.
48        reason: &'static str,
49    },
50    /// A non-structural event omitted explicit parent evidence.
51    #[error("event {event_id} requires at least one parent for role {role}")]
52    MissingParents {
53        /// Affected event.
54        event_id: SerialEventId,
55        /// Role name.
56        role: &'static str,
57    },
58    /// A parent event id did not resolve.
59    #[error("event {event_id} names unknown parent {parent_id}")]
60    UnknownParent {
61        /// Child event.
62        event_id: SerialEventId,
63        /// Missing parent id.
64        parent_id: SerialEventId,
65    },
66    /// A parent relation named the event itself.
67    #[error("event {0} cannot name itself as a parent")]
68    SelfParent(SerialEventId),
69    /// Parent evidence formed a cycle.
70    #[error("parent evidence contains a cycle involving event {0}")]
71    ParentCycle(SerialEventId),
72    /// Structural coverage failed to cover every ordinal of one row.
73    #[error("row {row_id} is missing structural coverage for ordinals {ordinals:?}")]
74    MissingStructuralCoverage {
75        /// Row instance lacking complete structural source coverage.
76        row_id: RowInstanceId,
77        /// Zero-based ordinals never cited by a structural event.
78        ordinals: Vec<usize>,
79    },
80    /// The precedence graph named an unknown event.
81    #[error("precedence graph names unknown event {0}")]
82    UnknownPrecedenceNode(SerialEventId),
83    /// The precedence graph contained a self-loop.
84    #[error("precedence graph contains a self-edge on event {0}")]
85    SelfPrecedence(SerialEventId),
86    /// The precedence graph contained a directed cycle.
87    #[error("precedence graph contains a cycle involving event {0}")]
88    PrecedenceCycle(SerialEventId),
89    /// Precedence claimed an ordering between events declared simultaneous.
90    #[error("precedence graph orders simultaneous-group {group_id} members {before} and {after}")]
91    SimultaneousPrecedenceConflict {
92        /// Simultaneous group shared by both events.
93        group_id: SimultaneousGroupId,
94        /// Event required to occur before the other.
95        before: SerialEventId,
96        /// Event required to occur after the other.
97        after: SerialEventId,
98    },
99    /// An event carried no ordinal references.
100    #[error("event {0} must reference at least one structural ordinal")]
101    EmptyOrdinalSet(SerialEventId),
102    /// The same ordinal was repeated within one event.
103    #[error("event {event_id} repeats ordinal reference {ordinal:?}")]
104    DuplicateOrdinal {
105        /// Affected event.
106        event_id: SerialEventId,
107        /// Repeated ordinal reference.
108        ordinal: OrdinalRef,
109    },
110    /// An event omitted the structural licenses required for reporting.
111    #[error("event {0} must declare at least one structural license")]
112    MissingStructuralLicenses(SerialEventId),
113    /// A structural license explanation was empty.
114    #[error("structural reading {0} must provide a non-empty rationale")]
115    EmptyStructuralLicenseRationale(StructuralReadingId),
116}