Skip to main content

xlog_core/
error.rs

1//! Error types for XLOG
2
3use thiserror::Error;
4
5/// Primary error type for XLOG operations
6#[derive(Debug, Error)]
7pub enum XlogError {
8    #[error("Parse error: {0}")]
9    Parse(String),
10
11    #[error("Stratification failed: cycle through negation involving {0:?}")]
12    StratificationCycle(Vec<String>),
13
14    #[error("Domain safety: variable {0} not bound in positive literal")]
15    UnsafeVariable(String),
16
17    #[error("Resource exhausted: {context}, estimated {estimated_bytes} bytes, budget {budget_bytes} bytes")]
18    ResourceExhausted {
19        context: String,
20        estimated_bytes: u64,
21        budget_bytes: u64,
22    },
23
24    #[error("Kernel error: {0}")]
25    Kernel(String),
26
27    #[error("Type error: {0}")]
28    Type(String),
29
30    #[error("Compilation error: {0}")]
31    Compilation(String),
32
33    #[error("Execution error: {0}")]
34    Execution(String),
35}
36
37impl XlogError {
38    /// Create a Kernel error with structured context: "op: detail: source".
39    pub fn kernel_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
40        XlogError::Kernel(format!("{op}: {detail}: {source}"))
41    }
42
43    /// Create an Execution error with structured context.
44    pub fn execution_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
45        XlogError::Execution(format!("{op}: {detail}: {source}"))
46    }
47
48    /// Create a Compilation error with structured context.
49    pub fn compilation_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
50        XlogError::Compilation(format!("{op}: {detail}: {source}"))
51    }
52}
53
54/// Result alias using XlogError
55pub type Result<T> = std::result::Result<T, XlogError>;
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_parse_error_display() {
63        let err = XlogError::Parse("unexpected token".to_string());
64        assert_eq!(err.to_string(), "Parse error: unexpected token");
65    }
66
67    #[test]
68    fn test_stratification_cycle_display() {
69        let err = XlogError::StratificationCycle(vec!["foo".to_string(), "bar".to_string()]);
70        assert!(err.to_string().contains("foo"));
71        assert!(err.to_string().contains("bar"));
72    }
73
74    #[test]
75    fn test_resource_exhausted_display() {
76        let err = XlogError::ResourceExhausted {
77            context: "join operation".to_string(),
78            estimated_bytes: 1024,
79            budget_bytes: 512,
80        };
81        assert!(err.to_string().contains("1024"));
82        assert!(err.to_string().contains("512"));
83    }
84
85    #[test]
86    fn test_kernel_ctx() {
87        let err = XlogError::kernel_ctx("download_column", "dtoh copy failed", &"device error 42");
88        assert_eq!(
89            err.to_string(),
90            "Kernel error: download_column: dtoh copy failed: device error 42"
91        );
92    }
93
94    #[test]
95    fn test_execution_ctx() {
96        let err = XlogError::execution_ctx("execute_node", "filter failed", &"type mismatch");
97        assert_eq!(
98            err.to_string(),
99            "Execution error: execute_node: filter failed: type mismatch"
100        );
101    }
102
103    #[test]
104    fn test_compilation_ctx() {
105        let err = XlogError::compilation_ctx("compile_d4", "frontier overflow", &"limit 1024");
106        assert_eq!(
107            err.to_string(),
108            "Compilation error: compile_d4: frontier overflow: limit 1024"
109        );
110    }
111}