1use std::path::PathBuf;
5
6use thiserror::Error;
7
8#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
10#[non_exhaustive]
11pub enum CacheRootProblem {
12 NotAbsolute,
14}
15
16#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
18#[non_exhaustive]
19pub enum CachePathProblem {
20 MissingParentDirectory,
22}
23
24#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
26#[non_exhaustive]
27pub enum CacheDirectoryProblem {
28 Symlink,
30 NotDirectory,
32 WrongOwner,
34 GroupOrOtherAccessible,
36}
37
38#[derive(Debug, Error)]
44#[non_exhaustive]
45pub enum ThumbnailError {
46 #[error("invalid thumbnail URI identity: {reason}")]
48 #[non_exhaustive]
49 InvalidUriIdentity {
50 reason: &'static str,
52 },
53 #[error("invalid cache namespace: {reason}")]
55 #[non_exhaustive]
56 InvalidNamespace {
57 reason: &'static str,
59 },
60 #[error("cache root could not be resolved: {reason}")]
62 #[non_exhaustive]
63 CacheRootUnavailable {
64 reason: &'static str,
66 },
67 #[error("invalid cache root {path:?}: {problem:?}")]
69 #[non_exhaustive]
70 InvalidCacheRoot {
71 path: PathBuf,
73 problem: CacheRootProblem,
75 },
76 #[error("invalid cache path {path:?}: {problem:?}")]
78 #[non_exhaustive]
79 InvalidCachePath {
80 path: PathBuf,
82 problem: CachePathProblem,
84 },
85 #[error("insecure cache directory {path:?}: {problem:?}")]
87 #[non_exhaustive]
88 InsecureCacheDirectory {
89 path: PathBuf,
91 problem: CacheDirectoryProblem,
93 },
94 #[error("{context}: {source}")]
96 #[non_exhaustive]
97 Io {
98 context: &'static str,
100 path: Option<PathBuf>,
102 #[source]
104 source: std::io::Error,
105 },
106 #[error("png error: {message}")]
108 #[non_exhaustive]
109 Png {
110 message: String,
112 },
113 #[error("invalid thumbnail metadata: {reason}")]
115 #[non_exhaustive]
116 InvalidMetadata {
117 reason: &'static str,
119 },
120 #[error("unsupported rendered thumbnail: {reason}")]
122 #[non_exhaustive]
123 UnsupportedRenderedThumbnail {
124 reason: &'static str,
126 },
127 #[error("resource limit exceeded: {reason}")]
129 #[non_exhaustive]
130 ResourceLimitExceeded {
131 reason: &'static str,
133 },
134 #[error("refused to remove cache entry: {reason}")]
136 #[non_exhaustive]
137 UnsafeRemoval {
138 reason: &'static str,
140 },
141}
142
143impl ThumbnailError {
144 pub(crate) const fn invalid_uri(reason: &'static str) -> Self {
145 Self::InvalidUriIdentity { reason }
146 }
147
148 pub(crate) const fn invalid_namespace(reason: &'static str) -> Self {
149 Self::InvalidNamespace { reason }
150 }
151
152 pub(crate) const fn cache_root_unavailable(reason: &'static str) -> Self {
153 Self::CacheRootUnavailable { reason }
154 }
155
156 pub(crate) const fn invalid_metadata(reason: &'static str) -> Self {
157 Self::InvalidMetadata { reason }
158 }
159
160 pub(crate) const fn unsupported_rendered_thumbnail(reason: &'static str) -> Self {
161 Self::UnsupportedRenderedThumbnail { reason }
162 }
163
164 pub(crate) const fn resource_limit_exceeded(reason: &'static str) -> Self {
165 Self::ResourceLimitExceeded { reason }
166 }
167
168 pub(crate) const fn unsafe_removal(reason: &'static str) -> Self {
169 Self::UnsafeRemoval { reason }
170 }
171
172 pub(crate) fn png(message: impl Into<String>) -> Self {
173 Self::Png {
174 message: message.into(),
175 }
176 }
177
178 pub(crate) fn io(
179 context: &'static str,
180 path: impl Into<Option<PathBuf>>,
181 source: std::io::Error,
182 ) -> Self {
183 Self::Io {
184 context,
185 path: path.into(),
186 source,
187 }
188 }
189}
190
191pub type Result<T, E = ThumbnailError> = std::result::Result<T, E>;