1use std::path::PathBuf;
4
5use thiserror::Error;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[repr(u8)]
11pub enum ExitCode {
12 Ok = 0,
14 Failure = 1,
16 MissingDependency = 2,
18 UserCancelled = 3,
20 ConfirmationMismatch = 4,
22 InvalidArgument = 5,
24}
25
26impl From<ExitCode> for u8 {
27 fn from(e: ExitCode) -> Self {
28 e as u8
29 }
30}
31
32#[derive(Debug, Error)]
36pub enum Error {
37 #[error("command `{cmd}` exited with status {status}: {stderr}")]
40 CommandFailed {
41 cmd: String,
42 status: i32,
43 stderr: String,
44 #[source]
45 io: Option<std::io::Error>,
46 },
47
48 #[error("missing dependency `{binary}`: {detail}")]
51 MissingDependency {
52 binary: String,
53 detail: String,
54 hint: Option<String>,
55 #[source]
56 io: Option<std::io::Error>,
57 },
58
59 #[error("config error: {0}")]
61 Config(#[from] ConfigError),
62
63 #[error("no matching NTFS volume for `{pattern}`")]
66 NoMatch { pattern: String },
67
68 #[error("confirmation mismatch: expected `{expected}`, got `{actual}`")]
70 ConfirmationMismatch { expected: String, actual: String },
71
72 #[error("user cancelled")]
74 Cancelled,
75
76 #[error("invalid argument: {0}")]
78 InvalidArgument(String),
79
80 #[error("i/o error: {0}")]
84 Io(#[from] std::io::Error),
85
86 #[error("serialization error: {0}")]
88 Serde(String),
89}
90
91#[derive(Debug, Error)]
92pub enum ConfigError {
93 #[error("failed to read config at {path}: {reason}")]
94 Read { path: PathBuf, reason: String },
95 #[error("failed to write config to {path}: {reason}")]
96 Write { path: PathBuf, reason: String },
97 #[error("config parse error at {path}: {reason}")]
98 Parse { path: PathBuf, reason: String },
99}
100
101impl From<ConfigError> for std::io::Error {
102 fn from(e: ConfigError) -> Self {
103 std::io::Error::other(e.to_string())
104 }
105}
106
107pub type Result<T> = std::result::Result<T, Error>;