1use serde::Serialize;
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
6#[serde(into = "u8")]
7pub enum ExitCode {
8 Success = 0,
9 General = 1,
10 InputFile = 2,
11 OutputIssue = 3,
12 Unsupported = 4,
13 BadArgs = 5,
14}
15
16impl From<ExitCode> for u8 {
17 fn from(code: ExitCode) -> u8 {
18 code as u8
19 }
20}
21
22#[derive(Debug, thiserror::Error, Serialize)]
24#[serde(tag = "error", rename_all = "snake_case")]
25pub enum PanimgError {
26 #[error("file not found: {path}")]
27 FileNotFound { path: PathBuf, suggestion: String },
28
29 #[error("permission denied: {path}")]
30 PermissionDenied { path: PathBuf, suggestion: String },
31
32 #[error("unsupported format: {format}")]
33 UnsupportedFormat { format: String, suggestion: String },
34
35 #[error("unknown format for: {path}")]
36 UnknownFormat { path: PathBuf, suggestion: String },
37
38 #[error("decode error: {message}")]
39 DecodeError {
40 message: String,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 path: Option<PathBuf>,
43 suggestion: String,
44 },
45
46 #[error("encode error: {message}")]
47 EncodeError {
48 message: String,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 path: Option<PathBuf>,
51 suggestion: String,
52 },
53
54 #[error("output already exists: {path}")]
55 OutputExists { path: PathBuf, suggestion: String },
56
57 #[error("invalid argument: {message}")]
58 InvalidArgument { message: String, suggestion: String },
59
60 #[error("resize error: {message}")]
61 ResizeError { message: String, suggestion: String },
62
63 #[error("io error: {message}")]
64 IoError {
65 message: String,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 path: Option<PathBuf>,
68 suggestion: String,
69 },
70}
71
72impl PanimgError {
73 pub fn exit_code(&self) -> ExitCode {
74 match self {
75 Self::FileNotFound { .. } | Self::PermissionDenied { .. } => ExitCode::InputFile,
76 Self::OutputExists { .. } => ExitCode::OutputIssue,
77 Self::UnsupportedFormat { .. } | Self::UnknownFormat { .. } => ExitCode::Unsupported,
78 Self::InvalidArgument { .. } => ExitCode::BadArgs,
79 Self::DecodeError { .. } => ExitCode::InputFile,
80 Self::EncodeError { .. } | Self::IoError { .. } => ExitCode::OutputIssue,
81 Self::ResizeError { .. } => ExitCode::General,
82 }
83 }
84
85 pub fn suggestion(&self) -> &str {
86 match self {
87 Self::FileNotFound { suggestion, .. }
88 | Self::PermissionDenied { suggestion, .. }
89 | Self::UnsupportedFormat { suggestion, .. }
90 | Self::UnknownFormat { suggestion, .. }
91 | Self::DecodeError { suggestion, .. }
92 | Self::EncodeError { suggestion, .. }
93 | Self::OutputExists { suggestion, .. }
94 | Self::InvalidArgument { suggestion, .. }
95 | Self::ResizeError { suggestion, .. }
96 | Self::IoError { suggestion, .. } => suggestion,
97 }
98 }
99}
100
101pub type Result<T> = std::result::Result<T, PanimgError>;