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>;