Skip to main content

tokenfold_core/
errors.rs

1#[derive(Debug, thiserror::Error)]
2pub enum TokenFoldError {
3    #[error("invalid input: {0}")]
4    InvalidInput(String),
5    #[error("safety violation: {0}")]
6    SafetyViolation(String),
7    #[error("redaction failed: {0}")]
8    RedactionFailed(String),
9    #[error("estimator error: {0}")]
10    EstimatorError(String),
11    #[error("config error: {0}")]
12    ConfigError(String),
13    #[error("internal error: {0}")]
14    InternalError(String),
15    #[error("io error: {0}")]
16    Io(#[from] std::io::Error),
17}
18
19impl TokenFoldError {
20    /// CLI exit code per the Error Taxonomy table (PLAN.md / INTERFACES.md ยง1.4).
21    pub fn exit_code(&self) -> i32 {
22        match self {
23            TokenFoldError::InvalidInput(_) => 2,
24            TokenFoldError::SafetyViolation(_) | TokenFoldError::RedactionFailed(_) => 3,
25            TokenFoldError::EstimatorError(_) => 4,
26            TokenFoldError::ConfigError(_) => 5,
27            TokenFoldError::InternalError(_) | TokenFoldError::Io(_) => 6,
28        }
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    fn exit_codes_match_error_taxonomy_table() {
38        assert_eq!(TokenFoldError::InvalidInput("x".into()).exit_code(), 2);
39        assert_eq!(TokenFoldError::SafetyViolation("x".into()).exit_code(), 3);
40        assert_eq!(TokenFoldError::RedactionFailed("x".into()).exit_code(), 3);
41        assert_eq!(TokenFoldError::EstimatorError("x".into()).exit_code(), 4);
42        assert_eq!(TokenFoldError::ConfigError("x".into()).exit_code(), 5);
43        assert_eq!(TokenFoldError::InternalError("x".into()).exit_code(), 6);
44        let io_err = TokenFoldError::from(std::io::Error::other("x"));
45        assert_eq!(io_err.exit_code(), 6);
46    }
47}