1use serde::{Deserialize, Serialize};
2use std::{
3 fmt,
4 fmt::{Display, Write},
5 str::FromStr,
6};
7use thiserror::Error;
8use throw_error::Error;
9use url::Url;
10
11pub const SERVER_FN_ERROR_HEADER: &str = "serverfnerror";
13
14impl From<ServerFnError> for Error {
15 fn from(e: ServerFnError) -> Self {
16 Error::from(ServerFnErrorErr::from(e))
17 }
18}
19
20#[derive(
23 Debug,
24 Deserialize,
25 Serialize,
26 PartialEq,
27 Eq,
28 Hash,
29 PartialOrd,
30 Ord,
31 Clone,
32 Copy,
33)]
34#[cfg_attr(
35 feature = "rkyv",
36 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
37)]
38pub struct NoCustomError;
39
40impl fmt::Display for NoCustomError {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 write!(f, "Unit Type Displayed")
44 }
45}
46
47impl FromStr for NoCustomError {
48 type Err = ();
49
50 fn from_str(_s: &str) -> Result<Self, Self::Err> {
51 Ok(NoCustomError)
52 }
53}
54
55#[derive(Debug)]
58pub struct WrapError<T>(pub T);
59
60#[macro_export]
63macro_rules! server_fn_error {
64 () => {{
65 use $crate::{ViaError, WrapError};
66 (&&&&&WrapError(())).to_server_error()
67 }};
68 ($err:expr) => {{
69 use $crate::error::{ViaError, WrapError};
70 match $err {
71 error => (&&&&&WrapError(error)).to_server_error(),
72 }
73 }};
74}
75
76pub trait ViaError<E> {
79 fn to_server_error(&self) -> ServerFnError<E>;
81}
82
83impl<E: ServerFnErrorKind + std::error::Error + Clone> ViaError<E>
85 for &&&&WrapError<ServerFnError<E>>
86{
87 fn to_server_error(&self) -> ServerFnError<E> {
88 self.0.clone()
89 }
90}
91
92pub(crate) trait ServerFnErrorKind {}
94
95impl ServerFnErrorKind for ServerFnError {}
96
97impl ViaError<NoCustomError> for &&&WrapError<()> {
99 fn to_server_error(&self) -> ServerFnError {
100 ServerFnError::WrappedServerError(NoCustomError)
101 }
102}
103
104impl<E: std::error::Error + Clone> ViaError<E> for &&WrapError<E> {
107 fn to_server_error(&self) -> ServerFnError<E> {
108 ServerFnError::WrappedServerError(self.0.clone())
109 }
110}
111
112impl<E: Display + Clone> ViaError<E> for &WrapError<E> {
115 fn to_server_error(&self) -> ServerFnError<E> {
116 ServerFnError::ServerError(self.0.to_string())
117 }
118}
119
120impl<E> ViaError<E> for WrapError<E> {
123 #[track_caller]
124 fn to_server_error(&self) -> ServerFnError<E> {
125 panic!(
126 "At {}, you call `to_server_error()` or use `server_fn_error!` \
127 with a value that does not implement `Clone` and either `Error` \
128 or `Display`.",
129 std::panic::Location::caller()
130 );
131 }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
140#[cfg_attr(
141 feature = "rkyv",
142 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
143)]
144pub enum ServerFnError<E = NoCustomError> {
145 WrappedServerError(E),
147 Registration(String),
149 Request(String),
151 Response(String),
153 ServerError(String),
155 Deserialization(String),
157 Serialization(String),
159 Args(String),
161 MissingArg(String),
163}
164
165impl ServerFnError<NoCustomError> {
166 pub fn new(msg: impl ToString) -> Self {
168 Self::ServerError(msg.to_string())
169 }
170}
171
172impl<CustErr> From<CustErr> for ServerFnError<CustErr> {
173 fn from(value: CustErr) -> Self {
174 ServerFnError::WrappedServerError(value)
175 }
176}
177
178impl<E: std::error::Error> From<E> for ServerFnError {
179 fn from(value: E) -> Self {
180 ServerFnError::ServerError(value.to_string())
181 }
182}
183
184impl<CustErr> Display for ServerFnError<CustErr>
185where
186 CustErr: Display,
187{
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 write!(
190 f,
191 "{}",
192 match self {
193 ServerFnError::Registration(s) => format!(
194 "error while trying to register the server function: {s}"
195 ),
196 ServerFnError::Request(s) => format!(
197 "error reaching server to call server function: {s}"
198 ),
199 ServerFnError::ServerError(s) =>
200 format!("error running server function: {s}"),
201 ServerFnError::Deserialization(s) =>
202 format!("error deserializing server function results: {s}"),
203 ServerFnError::Serialization(s) =>
204 format!("error serializing server function arguments: {s}"),
205 ServerFnError::Args(s) => format!(
206 "error deserializing server function arguments: {s}"
207 ),
208 ServerFnError::MissingArg(s) => format!("missing argument {s}"),
209 ServerFnError::Response(s) =>
210 format!("error generating HTTP response: {s}"),
211 ServerFnError::WrappedServerError(e) => format!("{e}"),
212 }
213 )
214 }
215}
216
217pub trait ServerFnErrorSerde: Sized {
227 fn ser(&self) -> Result<String, std::fmt::Error>;
229
230 fn de(data: &str) -> Self;
232}
233
234impl<CustErr> ServerFnErrorSerde for ServerFnError<CustErr>
235where
236 CustErr: FromStr + Display,
237{
238 fn ser(&self) -> Result<String, std::fmt::Error> {
239 let mut buf = String::new();
240 match self {
241 ServerFnError::WrappedServerError(e) => {
242 write!(&mut buf, "WrappedServerFn|{e}")
243 }
244 ServerFnError::Registration(e) => {
245 write!(&mut buf, "Registration|{e}")
246 }
247 ServerFnError::Request(e) => write!(&mut buf, "Request|{e}"),
248 ServerFnError::Response(e) => write!(&mut buf, "Response|{e}"),
249 ServerFnError::ServerError(e) => {
250 write!(&mut buf, "ServerError|{e}")
251 }
252 ServerFnError::Deserialization(e) => {
253 write!(&mut buf, "Deserialization|{e}")
254 }
255 ServerFnError::Serialization(e) => {
256 write!(&mut buf, "Serialization|{e}")
257 }
258 ServerFnError::Args(e) => write!(&mut buf, "Args|{e}"),
259 ServerFnError::MissingArg(e) => {
260 write!(&mut buf, "MissingArg|{e}")
261 }
262 }?;
263 Ok(buf)
264 }
265
266 fn de(data: &str) -> Self {
267 data.split_once('|')
268 .and_then(|(ty, data)| match ty {
269 "WrappedServerFn" => match CustErr::from_str(data) {
270 Ok(d) => Some(ServerFnError::WrappedServerError(d)),
271 Err(_) => None,
272 },
273 "Registration" => {
274 Some(ServerFnError::Registration(data.to_string()))
275 }
276 "Request" => Some(ServerFnError::Request(data.to_string())),
277 "Response" => Some(ServerFnError::Response(data.to_string())),
278 "ServerError" => {
279 Some(ServerFnError::ServerError(data.to_string()))
280 }
281 "Deserialization" => {
282 Some(ServerFnError::Deserialization(data.to_string()))
283 }
284 "Serialization" => {
285 Some(ServerFnError::Serialization(data.to_string()))
286 }
287 "Args" => Some(ServerFnError::Args(data.to_string())),
288 "MissingArg" => {
289 Some(ServerFnError::MissingArg(data.to_string()))
290 }
291 _ => None,
292 })
293 .unwrap_or_else(|| {
294 ServerFnError::Deserialization(format!(
295 "Could not deserialize error {data:?}"
296 ))
297 })
298 }
299}
300
301impl<E> std::error::Error for ServerFnError<E>
302where
303 E: std::error::Error + 'static,
304 ServerFnError<E>: std::fmt::Display,
305{
306 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
307 match self {
308 ServerFnError::WrappedServerError(e) => Some(e),
309 _ => None,
310 }
311 }
312}
313
314#[derive(Error, Debug, Clone, PartialEq, Eq)]
324pub enum ServerFnErrorErr<E = NoCustomError> {
325 #[error("internal error: {0}")]
327 WrappedServerError(E),
328 #[error("error while trying to register the server function: {0}")]
330 Registration(String),
331 #[error("error reaching server to call server function: {0}")]
333 Request(String),
334 #[error("error running server function: {0}")]
336 ServerError(String),
337 #[error("error deserializing server function results: {0}")]
339 Deserialization(String),
340 #[error("error serializing server function arguments: {0}")]
342 Serialization(String),
343 #[error("error deserializing server function arguments: {0}")]
345 Args(String),
346 #[error("missing argument {0}")]
348 MissingArg(String),
349 #[error("error creating response {0}")]
351 Response(String),
352}
353
354impl<CustErr> From<ServerFnError<CustErr>> for ServerFnErrorErr<CustErr> {
355 fn from(value: ServerFnError<CustErr>) -> Self {
356 match value {
357 ServerFnError::Registration(value) => {
358 ServerFnErrorErr::Registration(value)
359 }
360 ServerFnError::Request(value) => ServerFnErrorErr::Request(value),
361 ServerFnError::ServerError(value) => {
362 ServerFnErrorErr::ServerError(value)
363 }
364 ServerFnError::Deserialization(value) => {
365 ServerFnErrorErr::Deserialization(value)
366 }
367 ServerFnError::Serialization(value) => {
368 ServerFnErrorErr::Serialization(value)
369 }
370 ServerFnError::Args(value) => ServerFnErrorErr::Args(value),
371 ServerFnError::MissingArg(value) => {
372 ServerFnErrorErr::MissingArg(value)
373 }
374 ServerFnError::WrappedServerError(value) => {
375 ServerFnErrorErr::WrappedServerError(value)
376 }
377 ServerFnError::Response(value) => ServerFnErrorErr::Response(value),
378 }
379 }
380}
381
382#[derive(Debug)]
389pub struct ServerFnUrlError<CustErr> {
390 path: String,
391 error: ServerFnError<CustErr>,
392}
393
394impl<CustErr> ServerFnUrlError<CustErr> {
395 pub fn new(path: impl Display, error: ServerFnError<CustErr>) -> Self {
398 Self {
399 path: path.to_string(),
400 error,
401 }
402 }
403
404 pub fn error(&self) -> &ServerFnError<CustErr> {
406 &self.error
407 }
408
409 pub fn path(&self) -> &str {
411 &self.path
412 }
413
414 pub fn to_url(&self, base: &str) -> Result<Url, url::ParseError>
416 where
417 CustErr: FromStr + Display,
418 {
419 let mut url = Url::parse(base)?;
420 url.query_pairs_mut()
421 .append_pair("__path", &self.path)
422 .append_pair(
423 "__err",
424 &ServerFnErrorSerde::ser(&self.error).unwrap_or_default(),
425 );
426 Ok(url)
427 }
428
429 pub fn strip_error_info(path: &mut String) {
432 if let Ok(mut url) = Url::parse(&*path) {
433 let pairs_previously = url
436 .query_pairs()
437 .map(|(k, v)| (k.to_string(), v.to_string()))
438 .collect::<Vec<_>>();
439 let mut pairs = url.query_pairs_mut();
440 pairs.clear();
441 for (key, value) in pairs_previously
442 .into_iter()
443 .filter(|(key, _)| key != "__path" && key != "__err")
444 {
445 pairs.append_pair(&key, &value);
446 }
447 drop(pairs);
448 *path = url.to_string();
449 }
450 }
451}
452
453impl<CustErr> From<ServerFnUrlError<CustErr>> for ServerFnError<CustErr> {
454 fn from(error: ServerFnUrlError<CustErr>) -> Self {
455 error.error
456 }
457}
458
459impl<CustErr> From<ServerFnUrlError<CustErr>> for ServerFnErrorErr<CustErr> {
460 fn from(error: ServerFnUrlError<CustErr>) -> Self {
461 error.error.into()
462 }
463}