1use std::io;
15
16pub type Result<T> = std::result::Result<T, Error>;
18
19#[derive(Debug)]
20pub enum Error {
21 Io(io::Error),
22 Json(serde_json::Error),
23 Prompt(crate::prompt::PromptError),
24 Tmux(String),
25 MissingDep(&'static str),
26 SubprocessTimeout {
27 what: String,
28 ceiling_s: u64,
29 },
30 SubprocessFailed {
31 what: String,
32 code: i32,
33 },
34 Invalid(String),
35 Message(String),
39}
40
41impl Error {
42 pub fn msg(s: impl Into<String>) -> Self {
43 Self::Message(s.into())
44 }
45}
46
47impl std::fmt::Display for Error {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 Self::Io(e) => write!(f, "I/O: {e}"),
51 Self::Json(e) => write!(f, "JSON: {e}"),
52 Self::Prompt(e) => write!(f, "prompt: {e}"),
53 Self::Tmux(s) => write!(f, "tmux: {s}"),
54 Self::MissingDep(s) => write!(f, "missing dep on PATH: {s}"),
55 Self::SubprocessTimeout { what, ceiling_s } => {
56 write!(f, "subprocess `{what}` timed out after {ceiling_s}s")
57 }
58 Self::SubprocessFailed { what, code } => {
59 write!(f, "subprocess `{what}` failed (exit {code})")
60 }
61 Self::Invalid(s) => write!(f, "invalid input: {s}"),
62 Self::Message(s) => f.write_str(s),
63 }
64 }
65}
66
67impl std::error::Error for Error {
68 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69 match self {
70 Self::Io(e) => Some(e),
71 Self::Json(e) => Some(e),
72 Self::Prompt(e) => Some(e),
73 _ => None,
74 }
75 }
76}
77
78impl From<io::Error> for Error {
79 fn from(e: io::Error) -> Self {
80 Self::Io(e)
81 }
82}
83
84impl From<serde_json::Error> for Error {
85 fn from(e: serde_json::Error) -> Self {
86 Self::Json(e)
87 }
88}
89
90impl From<crate::prompt::PromptError> for Error {
91 fn from(e: crate::prompt::PromptError) -> Self {
92 Self::Prompt(e)
93 }
94}
95
96impl From<netsky_sh::Error> for Error {
97 fn from(e: netsky_sh::Error) -> Self {
98 Self::Tmux(format!("{e}"))
102 }
103}
104
105impl From<std::time::SystemTimeError> for Error {
106 fn from(e: std::time::SystemTimeError) -> Self {
107 Self::Message(format!("system time: {e}"))
108 }
109}
110
111impl From<std::num::ParseIntError> for Error {
112 fn from(e: std::num::ParseIntError) -> Self {
113 Self::Invalid(format!("parse int: {e}"))
114 }
115}
116
117#[macro_export]
121macro_rules! bail {
122 ($fmt:literal $(,)?) => {
123 return Err($crate::error::Error::Message(format!($fmt)))
124 };
125 ($fmt:expr, $($arg:tt)*) => {
126 return Err($crate::error::Error::Message(format!($fmt, $($arg)*)))
127 };
128}
129
130#[macro_export]
133macro_rules! anyhow {
134 ($fmt:literal $(,)?) => {
135 $crate::error::Error::Message(format!($fmt))
136 };
137 ($fmt:expr, $($arg:tt)*) => {
138 $crate::error::Error::Message(format!($fmt, $($arg)*))
139 };
140}