1use nils_common::cli_contract::exit;
4
5#[derive(Debug, Clone)]
8pub struct CommandError {
9 pub exit_code: i32,
10 pub code: String,
11 pub message: String,
12 pub hint: Option<String>,
13}
14
15impl CommandError {
16 fn new(exit_code: i32, code: impl Into<String>, message: impl Into<String>) -> Self {
17 Self {
18 exit_code,
19 code: code.into(),
20 message: message.into(),
21 hint: None,
22 }
23 }
24
25 pub fn usage(code: impl Into<String>, message: impl Into<String>) -> Self {
27 Self::new(exit::USAGE, code, message)
28 }
29
30 pub fn data(code: impl Into<String>, message: impl Into<String>) -> Self {
33 Self::new(exit::DATA, code, message)
34 }
35
36 pub fn unavailable(code: impl Into<String>, message: impl Into<String>) -> Self {
39 Self::new(exit::UNAVAILABLE, code, message)
40 }
41
42 pub fn with_hint(mut self, hint: impl Into<String>) -> Self {
44 self.hint = Some(hint.into());
45 self
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52 use pretty_assertions::assert_eq;
53
54 #[test]
55 fn exit_codes_match_category() {
56 assert_eq!(CommandError::usage("c", "m").exit_code, 64);
57 assert_eq!(CommandError::data("c", "m").exit_code, 65);
58 assert_eq!(CommandError::unavailable("c", "m").exit_code, 69);
59 }
60}