Skip to main content

rosalind/core/
error.rs

1//! Typed error taxonomy for the Rosalind core/library layer.
2//!
3//! The CLI boundary maps these into `anyhow`; library code returns `CoreError`.
4
5use thiserror::Error;
6
7/// Errors produced by the Rosalind core/library layer.
8#[derive(Debug, Error)]
9pub enum CoreError {
10    /// A streaming stage's working set would exceed the declared budget.
11    #[error("memory budget exceeded: working set {needed} bytes > budget {budget} bytes")]
12    BudgetExceeded {
13        /// Bytes the stage would require.
14        needed: u64,
15        /// Bytes the caller permitted.
16        budget: u64,
17    },
18    /// An input record could not be interpreted.
19    #[error("malformed record: {0}")]
20    MalformedRecord(String),
21    /// A contig id was not present in the active `ContigSet`.
22    #[error("invalid contig id {0}")]
23    InvalidContig(u32),
24    /// A read longer than the declared `--max-read-len` voids the predicted
25    /// memory envelope (raised only under `--enforce`).
26    #[error("read length {len} exceeds declared --max-read-len {declared}; raise --max-read-len or drop --enforce")]
27    ReadExceedsDeclaredLength {
28        /// The offending read's sequence length.
29        len: u32,
30        /// The declared cap.
31        declared: u32,
32    },
33    /// An underlying I/O failure.
34    #[error("io error: {0}")]
35    Io(#[from] std::io::Error),
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn budget_exceeded_displays_both_numbers() {
44        let e = CoreError::BudgetExceeded {
45            needed: 4096,
46            budget: 1024,
47        };
48        let msg = e.to_string();
49        assert!(
50            msg.contains("4096"),
51            "message should report needed bytes: {msg}"
52        );
53        assert!(
54            msg.contains("1024"),
55            "message should report budget bytes: {msg}"
56        );
57    }
58
59    #[test]
60    fn io_error_converts_via_from() {
61        let io = std::io::Error::new(std::io::ErrorKind::NotFound, "missing");
62        let e: CoreError = io.into();
63        assert!(matches!(e, CoreError::Io(_)));
64    }
65}