1use thiserror::Error;
4
5#[derive(Error, Debug)]
6#[non_exhaustive]
7pub enum SomaError {
8 #[error("filter requires labels (y) but none were provided")]
9 RequiresLabels,
10
11 #[error("cache error: {0}")]
12 Cache(String),
13
14 #[error("compilation error: {0}")]
15 Compilation(String),
16
17 #[error("execution error at node `{node_id}`: {message}")]
18 Execution { node_id: String, message: String },
19
20 #[error("trial pruned at step {step}: {reason}")]
21 Pruned { step: usize, reason: String },
22
23 #[error("schema mismatch: expected {expected}, got {got}")]
24 SchemaMismatch { expected: String, got: String },
25
26 #[error("node `{0}` not found in graph")]
27 NodeNotFound(String),
28
29 #[error("cycle detected in graph")]
30 CycleDetected,
31
32 #[error("serialization error: {0}")]
33 Serialization(String),
34
35 #[error("data store error: {0}")]
36 DataStore(String),
37
38 #[error("io error: {0}")]
39 Io(#[from] std::io::Error),
40
41 #[error("{0}")]
42 Other(String),
43}
44
45pub type Result<T> = std::result::Result<T, SomaError>;
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn error_display_messages() {
53 let err = SomaError::RequiresLabels;
54 assert_eq!(
55 err.to_string(),
56 "filter requires labels (y) but none were provided"
57 );
58
59 let err = SomaError::Execution {
60 node_id: "scaler_1".into(),
61 message: "dimension mismatch".into(),
62 };
63 assert_eq!(
64 err.to_string(),
65 "execution error at node `scaler_1`: dimension mismatch"
66 );
67
68 let err = SomaError::Pruned {
69 step: 5,
70 reason: "below median".into(),
71 };
72 assert_eq!(err.to_string(), "trial pruned at step 5: below median");
73 }
74
75 #[test]
76 fn result_type_alias_works() {
77 fn ok_fn() -> Result<i32> {
78 Ok(42)
79 }
80 fn err_fn() -> Result<i32> {
81 Err(SomaError::CycleDetected)
82 }
83 assert_eq!(ok_fn().unwrap(), 42);
84 assert!(err_fn().is_err());
85 }
86}