Skip to main content

panproto_schema/
error.rs

1//! Error types for schema operations.
2
3use std::fmt;
4
5/// Errors that can occur during schema construction and validation.
6#[derive(Debug, thiserror::Error)]
7#[non_exhaustive]
8pub enum SchemaError {
9    /// A vertex ID was referenced but not found in the schema.
10    #[error("vertex not found: {0}")]
11    VertexNotFound(String),
12
13    /// A duplicate vertex ID was added to the schema.
14    #[error("duplicate vertex id: {0}")]
15    DuplicateVertex(String),
16
17    /// A duplicate edge was added to the schema.
18    #[error("duplicate edge from {src} to {tgt} of kind {kind}")]
19    DuplicateEdge {
20        /// Source vertex ID.
21        src: String,
22        /// Target vertex ID.
23        tgt: String,
24        /// Edge kind.
25        kind: String,
26    },
27
28    /// A duplicate hyper-edge ID was added to the schema.
29    #[error("duplicate hyper-edge id: {0}")]
30    DuplicateHyperEdge(String),
31
32    /// An edge kind violates the protocol's edge rules.
33    #[error(
34        "invalid edge kind {kind}: source kind {src_kind} not allowed (permitted: {permitted})"
35    )]
36    InvalidEdgeSource {
37        /// The edge kind.
38        kind: String,
39        /// The actual source vertex kind.
40        src_kind: String,
41        /// Comma-separated list of permitted source kinds.
42        permitted: String,
43    },
44
45    /// An edge kind violates the protocol's edge rules (target).
46    #[error(
47        "invalid edge kind {kind}: target kind {tgt_kind} not allowed (permitted: {permitted})"
48    )]
49    InvalidEdgeTarget {
50        /// The edge kind.
51        kind: String,
52        /// The actual target vertex kind.
53        tgt_kind: String,
54        /// Comma-separated list of permitted target kinds.
55        permitted: String,
56    },
57
58    /// An edge kind is not recognized by the protocol.
59    #[error("unknown edge kind: {0}")]
60    UnknownEdgeKind(String),
61
62    /// A vertex kind is not recognized by the protocol's schema theory.
63    #[error("unknown vertex kind: {0}")]
64    UnknownVertexKind(String),
65
66    /// The schema has no vertices.
67    #[error("schema has no vertices")]
68    EmptySchema,
69
70    /// A declared entry vertex does not exist in the schema.
71    #[error("entry vertex not found: {0}")]
72    UnknownEntryVertex(String),
73
74    /// `SchemaBuilder::build_abstract` was called on a builder that
75    /// has accumulated constraints in the layout enrichment fibre.
76    /// Abstract schemas must carry no layout witnesses; call
77    /// `build_decorated` if a decorated schema was intended.
78    #[error(
79        "build_abstract called on a builder with layout-fibre constraints; \
80         use build_decorated for a decorated schema"
81    )]
82    LayoutConstraintsOnAbstractBuild,
83}
84
85/// An error found during schema validation against a protocol.
86#[derive(Debug, Clone, PartialEq, Eq)]
87#[non_exhaustive]
88pub enum ValidationError {
89    /// An edge violates the protocol's edge rules.
90    InvalidEdge {
91        /// The offending edge's source vertex ID.
92        src: String,
93        /// The offending edge's target vertex ID.
94        tgt: String,
95        /// The edge kind.
96        kind: String,
97        /// Human-readable reason for the violation.
98        reason: String,
99    },
100
101    /// A constraint uses a sort not recognized by the protocol.
102    InvalidConstraintSort {
103        /// The vertex with the invalid constraint.
104        vertex: String,
105        /// The unrecognized sort.
106        sort: String,
107    },
108
109    /// A vertex kind is not recognized by the protocol.
110    InvalidVertexKind {
111        /// The vertex ID.
112        vertex: String,
113        /// The unrecognized kind.
114        kind: String,
115    },
116
117    /// A required edge references a missing vertex.
118    DanglingRequiredEdge {
119        /// The vertex ID.
120        vertex: String,
121        /// The dangling edge description.
122        edge: String,
123    },
124}
125
126impl fmt::Display for ValidationError {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        match self {
129            Self::InvalidEdge {
130                src,
131                tgt,
132                kind,
133                reason,
134            } => write!(f, "invalid edge {src} -> {tgt} ({kind}): {reason}"),
135            Self::InvalidConstraintSort { vertex, sort } => {
136                write!(f, "vertex {vertex} has invalid constraint sort: {sort}")
137            }
138            Self::InvalidVertexKind { vertex, kind } => {
139                write!(f, "vertex {vertex} has invalid kind: {kind}")
140            }
141            Self::DanglingRequiredEdge { vertex, edge } => {
142                write!(f, "vertex {vertex} has dangling required edge: {edge}")
143            }
144        }
145    }
146}