Skip to main content

proc_cli/
error.rs

1//! Error types for proc CLI
2//!
3//! Provides structured error handling with helpful suggestions for users.
4
5use thiserror::Error;
6
7/// Main error type for proc operations
8#[derive(Error, Debug)]
9pub enum ProcError {
10    /// No process found matching the given target
11    #[error("No process found matching '{0}'\n  Try: proc list to list all processes")]
12    ProcessNotFound(String),
13
14    /// No process is listening on the specified port
15    #[error("No process listening on port {0}\n  Try: proc ports")]
16    PortNotFound(u16),
17
18    /// Insufficient permissions to operate on the process
19    #[error("Permission denied for PID {0}\n  Try: sudo proc <command>")]
20    PermissionDenied(u32),
21
22    /// User provided invalid input or arguments
23    #[error("Invalid input: {0}")]
24    InvalidInput(String),
25
26    /// An underlying system call failed
27    #[error("System error: {0}")]
28    SystemError(String),
29
30    /// The operation exceeded the allowed time limit
31    #[error("Operation timed out: {0}")]
32    Timeout(String),
33
34    /// Failed to parse input or system output
35    #[error("Failed to parse: {0}")]
36    ParseError(String),
37
38    /// Feature is not available on the current platform
39    #[error("Not supported on this platform: {0}")]
40    NotSupported(String),
41
42    /// The target process terminated during the operation
43    #[error("Process {0} is no longer running")]
44    ProcessGone(u32),
45
46    /// Failed to send a signal to the process
47    #[error("Signal failed: {0}")]
48    SignalError(String),
49}
50
51impl From<std::io::Error> for ProcError {
52    fn from(err: std::io::Error) -> Self {
53        match err.kind() {
54            std::io::ErrorKind::PermissionDenied => ProcError::PermissionDenied(0),
55            std::io::ErrorKind::NotFound => ProcError::ProcessNotFound("unknown".to_string()),
56            _ => ProcError::SystemError(err.to_string()),
57        }
58    }
59}
60
61impl From<serde_json::Error> for ProcError {
62    fn from(err: serde_json::Error) -> Self {
63        ProcError::ParseError(err.to_string())
64    }
65}
66
67impl From<regex::Error> for ProcError {
68    fn from(err: regex::Error) -> Self {
69        ProcError::InvalidInput(format!("Invalid pattern: {}", err))
70    }
71}
72
73impl From<dialoguer::Error> for ProcError {
74    fn from(err: dialoguer::Error) -> Self {
75        ProcError::SystemError(format!("Dialog error: {}", err))
76    }
77}
78
79/// Result type alias for proc operations
80pub type Result<T> = std::result::Result<T, ProcError>;
81
82/// Exit codes for CLI
83#[derive(Debug, Clone, Copy)]
84pub enum ExitCode {
85    /// Operation completed successfully
86    Success = 0,
87    /// A general error occurred
88    GeneralError = 1,
89    /// The requested process or port was not found
90    NotFound = 2,
91    /// Operation requires elevated privileges
92    PermissionDenied = 3,
93    /// Invalid arguments or input provided
94    InvalidInput = 4,
95}
96
97impl From<&ProcError> for ExitCode {
98    fn from(err: &ProcError) -> Self {
99        match err {
100            ProcError::ProcessNotFound(_) | ProcError::PortNotFound(_) => ExitCode::NotFound,
101            ProcError::PermissionDenied(_) => ExitCode::PermissionDenied,
102            ProcError::InvalidInput(_) => ExitCode::InvalidInput,
103            _ => ExitCode::GeneralError,
104        }
105    }
106}