1use std::fmt;
4
5pub const OK: i32 = 0;
6pub const ERROR: i32 = 1;
7pub const TIMEOUT: i32 = 2;
8pub const AUTH: i32 = 3;
9pub const NOT_FOUND: i32 = 4;
10pub const STALE: i32 = 5;
12
13#[derive(Debug)]
15pub struct Exit {
16 pub code: i32,
17 pub message: String,
18}
19
20impl fmt::Display for Exit {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.write_str(&self.message)
23 }
24}
25
26impl std::error::Error for Exit {}
27
28pub fn auth(message: impl Into<String>) -> anyhow::Error {
29 Exit {
30 code: AUTH,
31 message: message.into(),
32 }
33 .into()
34}
35
36pub fn not_found(message: impl Into<String>) -> anyhow::Error {
37 Exit {
38 code: NOT_FOUND,
39 message: message.into(),
40 }
41 .into()
42}
43
44pub fn timeout(message: impl Into<String>) -> anyhow::Error {
45 Exit {
46 code: TIMEOUT,
47 message: message.into(),
48 }
49 .into()
50}
51
52pub fn stale(message: impl Into<String>) -> anyhow::Error {
53 Exit {
54 code: STALE,
55 message: message.into(),
56 }
57 .into()
58}
59
60pub fn code_of(err: &anyhow::Error) -> i32 {
62 err.downcast_ref::<Exit>().map(|e| e.code).unwrap_or(ERROR)
63}
64
65pub fn is_not_found(err: &anyhow::Error) -> bool {
66 code_of(err) == NOT_FOUND
67}
68
69pub fn is_stale(err: &anyhow::Error) -> bool {
70 code_of(err) == STALE
71}
72
73pub fn message_of(err: &anyhow::Error) -> String {
75 match err.downcast_ref::<Exit>() {
76 Some(x) => x.message.clone(),
77 None => format!("{err:#}"),
78 }
79}
80
81#[derive(Debug)]
83pub struct Conflict(pub String);
84
85impl fmt::Display for Conflict {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 f.write_str(&self.0)
88 }
89}
90
91impl std::error::Error for Conflict {}
92
93pub fn is_conflict(err: &anyhow::Error) -> bool {
94 err.downcast_ref::<Conflict>().is_some()
95}