1use miette::Diagnostic;
4use thiserror::Error;
5
6#[derive(Error, Diagnostic, Debug)]
8pub enum PackageError {
9 #[error("Error while {action}: {source}")]
10 #[diagnostic(code(soar_package::io))]
11 IoError {
12 action: String,
13 source: std::io::Error,
14 },
15
16 #[error("Failed to read magic bytes")]
17 #[diagnostic(code(soar_package::magic_bytes))]
18 MagicBytesError,
19
20 #[error("Failed to seek in file")]
21 #[diagnostic(code(soar_package::seek))]
22 SeekError,
23
24 #[error(transparent)]
25 #[diagnostic(code(soar_package::image))]
26 ImageError(#[from] image::ImageError),
27
28 #[error(transparent)]
29 #[diagnostic(code(soar_package::appimage))]
30 AppImageError(#[from] squishy::error::SquishyError),
31
32 #[error("Configuration error: {0}")]
33 #[diagnostic(code(soar_package::config))]
34 ConfigError(String),
35
36 #[error("{0}")]
37 #[diagnostic(code(soar_package::custom))]
38 Custom(String),
39}
40
41pub type Result<T> = std::result::Result<T, PackageError>;
43
44pub trait ErrorContext<T> {
46 fn with_context<C>(self, context: C) -> Result<T>
48 where
49 C: FnOnce() -> String;
50}
51
52impl<T> ErrorContext<T> for std::io::Result<T> {
53 fn with_context<C>(self, context: C) -> Result<T>
54 where
55 C: FnOnce() -> String,
56 {
57 self.map_err(|err| {
58 PackageError::IoError {
59 action: context(),
60 source: err,
61 }
62 })
63 }
64}
65
66impl From<soar_config::error::ConfigError> for PackageError {
67 fn from(err: soar_config::error::ConfigError) -> Self {
68 PackageError::ConfigError(err.to_string())
69 }
70}
71
72impl From<soar_utils::error::FileSystemError> for PackageError {
73 fn from(err: soar_utils::error::FileSystemError) -> Self {
74 PackageError::Custom(err.to_string())
75 }
76}