1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum AlignmentError {
5 #[error("I/O error while {context}: {source}")]
6 Io {
7 context: &'static str,
8 #[source]
9 source: std::io::Error,
10 },
11 #[error("JSON parse error while {context}: {source}")]
12 Json {
13 context: &'static str,
14 #[source]
15 source: serde_json::Error,
16 },
17 #[error("{context}: {message}")]
18 Runtime {
19 context: &'static str,
20 message: String,
21 },
22 #[error("invalid input: {message}")]
23 InvalidInput { message: String },
24}
25
26impl AlignmentError {
27 pub(crate) fn io(context: &'static str, source: std::io::Error) -> Self {
28 Self::Io { context, source }
29 }
30
31 pub(crate) fn json(context: &'static str, source: serde_json::Error) -> Self {
32 Self::Json { context, source }
33 }
34
35 pub(crate) fn runtime(context: &'static str, err: impl std::fmt::Display) -> Self {
36 Self::Runtime {
37 context,
38 message: err.to_string(),
39 }
40 }
41
42 pub(crate) fn invalid_input(message: impl Into<String>) -> Self {
43 Self::InvalidInput {
44 message: message.into(),
45 }
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use std::error::Error;
53
54 #[test]
55 fn io_error_constructor_and_display() {
56 let source = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
57 let err = AlignmentError::io("reading model", source);
58 let display = err.to_string();
59 assert!(display.contains("I/O error"));
60 assert!(display.contains("reading model"));
61 assert!(err.source().is_some());
62 }
63
64 #[test]
65 fn json_error_constructor_and_display() {
66 let source = serde_json::from_str::<()>("{").unwrap_err();
67 let err = AlignmentError::json("parse config.json", source);
68 let display = err.to_string();
69 assert!(display.contains("JSON parse error"));
70 assert!(display.contains("parse config.json"));
71 assert!(err.source().is_some());
72 }
73
74 #[test]
75 fn runtime_error_constructor_and_display() {
76 let err = AlignmentError::runtime("alignment", "buffer too short");
77 let display = err.to_string();
78 assert!(display.contains("alignment"));
79 assert!(display.contains("buffer too short"));
80 assert!(err.source().is_none());
81 }
82
83 #[test]
84 fn invalid_input_constructor_and_display() {
85 let err = AlignmentError::invalid_input("sample rate must be 16000");
86 let display = err.to_string();
87 assert!(display.contains("invalid input"));
88 assert!(display.contains("sample rate must be 16000"));
89 assert!(err.source().is_none());
90 }
91}