Skip to main content

weavatrix_graph/
error.rs

1use crate::String;
2use core::fmt::{Display, Formatter};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5#[non_exhaustive]
6pub enum GraphError {
7    EmptyNodeId,
8    InvalidKind {
9        category: &'static str,
10        value: String,
11    },
12    ConflictingNode {
13        id: String,
14    },
15    MissingEdgeSource {
16        id: String,
17    },
18    MissingEdgeTarget {
19        id: String,
20    },
21    EmptyExtractor,
22    InvalidSpan {
23        file: String,
24        reason: &'static str,
25    },
26    IndexCapacityExceeded {
27        category: &'static str,
28        count: usize,
29    },
30    InvalidTopologyEndpoint {
31        edge: usize,
32        node: usize,
33        node_count: usize,
34    },
35    ArithmeticOverflow {
36        operation: &'static str,
37    },
38    InvalidNodeIndex {
39        node: usize,
40        node_count: usize,
41    },
42    InvalidProbability {
43        numerator: u64,
44        denominator: u64,
45    },
46    InvalidAlgorithmParameter {
47        algorithm: &'static str,
48        parameter: &'static str,
49        value: String,
50    },
51    NegativeCycle {
52        algorithm: &'static str,
53    },
54    CyclicGraph {
55        algorithm: &'static str,
56    },
57    InvalidFormat {
58        format: &'static str,
59        reason: String,
60    },
61    UnsupportedGraphFeature {
62        format: &'static str,
63        feature: &'static str,
64    },
65    PayloadCountMismatch {
66        category: &'static str,
67        expected: usize,
68        actual: usize,
69    },
70    InvalidStableKey {
71        category: &'static str,
72        slot: u32,
73        generation: u32,
74    },
75    MissingKeyedNode {
76        endpoint: &'static str,
77    },
78    CycleWouldBeCreated,
79}
80
81impl Display for GraphError {
82    fn fmt(&self, formatter: &mut Formatter<'_>) -> core::fmt::Result {
83        match self {
84            Self::EmptyNodeId => formatter.write_str("node id must not be empty"),
85            Self::InvalidKind { category, value } => {
86                write!(formatter, "invalid {category} kind: {value:?}")
87            }
88            Self::ConflictingNode { id } => {
89                write!(formatter, "node id {id} has conflicting definitions")
90            }
91            Self::MissingEdgeSource { id } => {
92                write!(formatter, "edge source does not exist: {id}")
93            }
94            Self::MissingEdgeTarget { id } => {
95                write!(formatter, "edge target does not exist: {id}")
96            }
97            Self::EmptyExtractor => formatter.write_str("provenance extractor must not be empty"),
98            Self::InvalidSpan { file, reason } => {
99                write!(formatter, "invalid source span for {file:?}: {reason}")
100            }
101            Self::IndexCapacityExceeded { category, count } => {
102                write!(
103                    formatter,
104                    "{category} count {count} exceeds u32 index capacity"
105                )
106            }
107            Self::InvalidTopologyEndpoint {
108                edge,
109                node,
110                node_count,
111            } => write!(
112                formatter,
113                "edge {edge} references node index {node}, but node count is {node_count}"
114            ),
115            Self::ArithmeticOverflow { operation } => {
116                write!(formatter, "arithmetic overflow while computing {operation}")
117            }
118            Self::InvalidNodeIndex { node, node_count } => {
119                write!(
120                    formatter,
121                    "node index {node} is outside matrix node count {node_count}"
122                )
123            }
124            Self::InvalidProbability {
125                numerator,
126                denominator,
127            } => write!(
128                formatter,
129                "probability {numerator}/{denominator} must have a nonzero denominator and be at most one"
130            ),
131            Self::InvalidAlgorithmParameter {
132                algorithm,
133                parameter,
134                value,
135            } => write!(formatter, "invalid {parameter} for {algorithm}: {value}"),
136            Self::NegativeCycle { algorithm } => {
137                write!(formatter, "{algorithm} found a reachable negative cycle")
138            }
139            Self::CyclicGraph { algorithm } => {
140                write!(formatter, "{algorithm} requires an acyclic graph")
141            }
142            Self::InvalidFormat { format, reason } => {
143                write!(formatter, "invalid {format} input: {reason}")
144            }
145            Self::UnsupportedGraphFeature { format, feature } => {
146                write!(formatter, "{format} does not support {feature}")
147            }
148            Self::PayloadCountMismatch {
149                category,
150                expected,
151                actual,
152            } => write!(
153                formatter,
154                "{category} payload count {actual} does not match topology count {expected}"
155            ),
156            Self::InvalidStableKey {
157                category,
158                slot,
159                generation,
160            } => write!(
161                formatter,
162                "{category} key at slot {slot}, generation {generation} is stale or invalid"
163            ),
164            Self::MissingKeyedNode { endpoint } => {
165                write!(formatter, "keyed graph {endpoint} node does not exist")
166            }
167            Self::CycleWouldBeCreated => {
168                formatter.write_str("mutation would violate the acyclic graph invariant")
169            }
170        }
171    }
172}
173
174impl core::error::Error for GraphError {}
175
176pub type Result<T> = core::result::Result<T, GraphError>;