1use std::io;
2
3use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug, Error)]
10pub enum Error {
11 #[error("binary '{binary}' not found on PATH")]
13 BinaryNotFound {
14 binary: String,
16 },
17
18 #[error("{binary} failed (code: {exit_code:?}): {message}")]
20 CommandFailed {
21 binary: String,
23 exit_code: Option<i32>,
25 message: String,
27 },
28
29 #[error(transparent)]
31 Io(#[from] io::Error),
32
33 #[error(transparent)]
35 Json(#[from] serde_json::Error),
36
37 #[error("invalid input: {0}")]
39 InvalidInput(String),
40
41 #[error("parse error: {0}")]
43 Parse(String),
44
45 #[error("unsupported operation: {0}")]
47 Unsupported(String),
48}
49
50impl Error {
51 pub(crate) fn command_failed(binary: &str, exit_code: Option<i32>, stderr: &[u8]) -> Self {
53 let message = truncate(stderr);
54 Error::CommandFailed {
55 binary: binary.to_string(),
56 exit_code,
57 message,
58 }
59 }
60}
61
62fn truncate(message: &[u8]) -> String {
63 const MAX: usize = 4096;
64 let mut text = String::from_utf8_lossy(message).into_owned();
65 if text.len() > MAX {
66 text.truncate(MAX);
67 text.push_str("…");
68 }
69 text
70}