rightkit_tauri_shell/
error.rs1use serde::Serialize;
9
10#[derive(Debug, Serialize, Clone, PartialEq, Eq)]
11#[serde(tag = "code", content = "message", rename_all = "snake_case")]
12pub enum ShellError {
13 BrokerDenied(String),
15 FileNotFound(String),
16 PermissionDenied(String),
18 UnsupportedFormat(String),
19 DocumentTooLarge(String),
20 Io(String),
21 Encoding(String),
22 WriteConflict(String),
23 Invalid(String),
25 Unsupported(String),
27 Timeout(String),
29 Other(String),
30}
31
32impl ShellError {
33 pub fn code(&self) -> &'static str {
34 match self {
35 Self::BrokerDenied(_) => "broker_denied",
36 Self::FileNotFound(_) => "file_not_found",
37 Self::PermissionDenied(_) => "permission_denied",
38 Self::UnsupportedFormat(_) => "unsupported_format",
39 Self::DocumentTooLarge(_) => "document_too_large",
40 Self::Io(_) => "io",
41 Self::Encoding(_) => "encoding",
42 Self::WriteConflict(_) => "write_conflict",
43 Self::Invalid(_) => "invalid",
44 Self::Unsupported(_) => "unsupported",
45 Self::Timeout(_) => "timeout",
46 Self::Other(_) => "other",
47 }
48 }
49 pub fn message(&self) -> &str {
50 match self {
51 Self::BrokerDenied(m)
52 | Self::FileNotFound(m)
53 | Self::PermissionDenied(m)
54 | Self::UnsupportedFormat(m)
55 | Self::DocumentTooLarge(m)
56 | Self::Io(m)
57 | Self::Encoding(m)
58 | Self::WriteConflict(m)
59 | Self::Invalid(m)
60 | Self::Unsupported(m)
61 | Self::Timeout(m)
62 | Self::Other(m) => m,
63 }
64 }
65}
66
67impl std::fmt::Display for ShellError {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 let label = match self {
70 Self::BrokerDenied(_) => "access denied",
71 Self::FileNotFound(_) => "file not found",
72 Self::PermissionDenied(_) => "permission denied",
73 Self::UnsupportedFormat(_) => "unsupported format",
74 Self::DocumentTooLarge(_) => "document too large",
75 Self::Io(_) => "I/O error",
76 Self::Encoding(_) => "encoding error",
77 Self::WriteConflict(_) => "write conflict",
78 Self::Invalid(_) => "invalid request",
79 Self::Unsupported(_) => "unsupported",
80 Self::Timeout(_) => "timed out",
81 Self::Other(_) => return write!(f, "{}", self.message()),
82 };
83 write!(f, "{label}: {}", self.message())
84 }
85}
86
87impl std::error::Error for ShellError {}
88
89impl From<String> for ShellError {
90 fn from(s: String) -> Self {
91 broker_error(s)
92 }
93}
94impl From<&str> for ShellError {
95 fn from(s: &str) -> Self {
96 broker_error(s.to_owned())
97 }
98}
99
100impl From<std::io::Error> for ShellError {
101 fn from(e: std::io::Error) -> Self {
102 use std::io::ErrorKind::*;
103 match e.kind() {
104 NotFound => Self::FileNotFound(e.to_string()),
105 PermissionDenied => Self::PermissionDenied(e.to_string()),
106 _ => Self::Io(e.to_string()),
107 }
108 }
109}
110
111pub fn broker_error(message: String) -> ShellError {
113 let lower = message.to_ascii_lowercase();
114 if lower.contains("not authorized")
115 || lower.contains("not just written")
116 || lower.contains("unknown or revoked")
117 || lower.contains("unknown or already-used")
118 {
119 ShellError::BrokerDenied(message)
120 } else if lower.contains("no such file")
121 || lower.contains("cannot find the path")
122 || lower.contains("cannot find the file")
123 || lower.contains("not a file")
124 {
125 ShellError::FileNotFound(message)
126 } else if lower.contains("permission denied") || lower.contains("operation not permitted") {
127 ShellError::PermissionDenied(message)
128 } else {
129 ShellError::Other(message)
130 }
131}