Skip to main content

toggle/
exit_codes.rs

1use std::fmt;
2
3/// Typed error for bad CLI input / range errors (maps to ExitCode::Usage).
4/// Use this instead of bare `anyhow!()` for usage errors so that
5/// `classify_error` can downcast instead of matching on message strings.
6#[derive(Debug)]
7pub struct UsageError(pub String);
8
9impl fmt::Display for UsageError {
10    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
11        f.write_str(&self.0)
12    }
13}
14
15impl std::error::Error for UsageError {}
16
17/// Exit codes per Phase 0 PRD ยง0.8
18#[derive(Debug, Clone, Copy)]
19pub enum ExitCode {
20    /// EC00: Success
21    Success = 0,
22    /// EC01: Bad CLI / range
23    Usage = 1,
24    /// EC02: File R/W error
25    IoError = 2,
26    /// EC03: Toggle logic issue
27    ToggleError = 3,
28    /// EC04: Internal panic (reserved for future panic hook, not yet wired)
29    #[allow(dead_code)]
30    Internal = 4,
31}
32
33impl ExitCode {
34    /// Map to sysexits.h values for --posix-exit
35    pub fn posix(self) -> i32 {
36        match self {
37            Self::Success => 0,      // EX_OK
38            Self::Usage => 64,       // EX_USAGE
39            Self::IoError => 74,     // EX_IOERR
40            Self::ToggleError => 70, // EX_SOFTWARE
41            Self::Internal => 71,    // EX_OSERR
42        }
43    }
44
45    /// Get the numeric value
46    pub fn code(self) -> i32 {
47        self as i32
48    }
49}