use std::fmt;
use std::io;
use std::path::PathBuf;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, MbrkitError>;
#[derive(Debug, Error)]
pub enum MbrkitError {
#[error("{message}{path_suffix}")]
Io {
path: Option<PathBuf>,
message: String,
#[source]
source: io::Error,
path_suffix: PathSuffix,
},
#[error("{0}")]
InvalidArgument(String),
#[error("invalid partition spec `{spec}`: {message}")]
InvalidPartitionSpec {
spec: String,
message: String,
},
#[error("invalid size `{value}`")]
InvalidSize {
value: String,
},
#[error("invalid partition type `{value}`")]
InvalidPartitionType {
value: String,
},
#[error("{0}")]
InvalidMbr(String),
#[error("")]
SilentFailure(i32),
#[error("failed to serialize report: {0}")]
Serialize(#[from] serde_json::Error),
#[error("failed to parse manifest `{path}`: {source}")]
Manifest {
path: String,
#[source]
source: toml::de::Error,
},
}
#[derive(Clone, Debug)]
pub struct PathSuffix(pub String);
impl fmt::Display for PathSuffix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl MbrkitError {
pub fn io(path: Option<PathBuf>, message: impl Into<String>, source: io::Error) -> Self {
let path_suffix = match &path {
Some(value) => PathSuffix(format!(" ({})", value.display())),
None => PathSuffix(String::new()),
};
Self::Io {
path,
message: message.into(),
source,
path_suffix,
}
}
pub fn exit_code(&self) -> i32 {
match self {
Self::SilentFailure(code) => *code,
Self::InvalidArgument(_)
| Self::InvalidPartitionSpec { .. }
| Self::InvalidSize { .. }
| Self::InvalidPartitionType { .. } => 2,
_ => 1,
}
}
pub fn should_print(&self) -> bool {
!matches!(self, Self::SilentFailure(_))
}
}