1use thiserror::Error;
4
5#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum XlogError {
9 #[error("Parse error: {0}")]
11 Parse(String),
12
13 #[error("Stratification failed: cycle through negation involving {0:?}")]
15 StratificationCycle(Vec<String>),
16
17 #[error("Domain safety: variable {0} not bound in positive literal")]
19 UnsafeVariable(String),
20
21 #[error("Resource exhausted: {context}, estimated {estimated_bytes} bytes, budget {budget_bytes} bytes")]
23 ResourceExhausted {
24 context: String,
26 estimated_bytes: u64,
28 budget_bytes: u64,
30 },
31
32 #[error("D4 compile declined: {context}: {detail}")]
39 CompileCapacityExceeded {
40 context: String,
42 detail: String,
44 },
45
46 #[error("D4 equivalence verify declined: {context}: {detail}")]
54 VerifyBudgetExceeded {
55 context: String,
57 detail: String,
59 },
60
61 #[error("Kernel error: {0}")]
63 Kernel(String),
64
65 #[error("Type error: {0}")]
67 Type(String),
68
69 #[error("Compilation error: {0}")]
71 Compilation(String),
72
73 #[error("Unsupported epistemic construct: {construct} ({context})")]
75 UnsupportedEpistemicConstruct {
76 construct: String,
78 context: String,
80 },
81
82 #[error(
84 "Constraint {constraint_index} violated: {relation_name} produced {witness_rows} witness row(s)"
85 )]
86 ConstraintViolation {
87 constraint_index: usize,
89 relation_name: String,
91 witness_rows: usize,
93 },
94
95 #[error("Execution error: {0}")]
97 Execution(String),
98}
99
100impl XlogError {
101 pub fn kernel_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
103 XlogError::Kernel(format!("{op}: {detail}: {source}"))
104 }
105
106 pub fn execution_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
108 XlogError::Execution(format!("{op}: {detail}: {source}"))
109 }
110
111 pub fn compilation_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
113 XlogError::Compilation(format!("{op}: {detail}: {source}"))
114 }
115}
116
117pub type Result<T> = std::result::Result<T, XlogError>;
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_parse_error_display() {
126 let err = XlogError::Parse("unexpected token".to_string());
127 assert_eq!(err.to_string(), "Parse error: unexpected token");
128 }
129
130 #[test]
131 fn test_stratification_cycle_display() {
132 let err = XlogError::StratificationCycle(vec!["foo".to_string(), "bar".to_string()]);
133 assert!(err.to_string().contains("foo"));
134 assert!(err.to_string().contains("bar"));
135 }
136
137 #[test]
138 fn test_resource_exhausted_display() {
139 let err = XlogError::ResourceExhausted {
140 context: "join operation".to_string(),
141 estimated_bytes: 1024,
142 budget_bytes: 512,
143 };
144 assert!(err.to_string().contains("1024"));
145 assert!(err.to_string().contains("512"));
146 }
147
148 #[test]
149 fn test_constraint_violation_display() {
150 let err = XlogError::ConstraintViolation {
151 constraint_index: 3,
152 relation_name: "__xlog_constraint_3".to_string(),
153 witness_rows: 2,
154 };
155 assert_eq!(
156 err.to_string(),
157 "Constraint 3 violated: __xlog_constraint_3 produced 2 witness row(s)"
158 );
159 }
160
161 #[test]
162 fn test_kernel_ctx() {
163 let err = XlogError::kernel_ctx("download_column", "dtoh copy failed", &"device error 42");
164 assert_eq!(
165 err.to_string(),
166 "Kernel error: download_column: dtoh copy failed: device error 42"
167 );
168 }
169
170 #[test]
171 fn test_execution_ctx() {
172 let err = XlogError::execution_ctx("execute_node", "filter failed", &"type mismatch");
173 assert_eq!(
174 err.to_string(),
175 "Execution error: execute_node: filter failed: type mismatch"
176 );
177 }
178
179 #[test]
180 fn test_compilation_ctx() {
181 let err = XlogError::compilation_ctx("compile_d4", "frontier overflow", &"limit 1024");
182 assert_eq!(
183 err.to_string(),
184 "Compilation error: compile_d4: frontier overflow: limit 1024"
185 );
186 }
187}