1#![doc = "Error types."]
2use http::{HeaderValue, StatusCode};
3use serde::{Deserialize, Serialize};
4use std::fmt::{self, Debug, Display};
5
6#[derive(thiserror::Error, Debug)]
8pub enum Error<E>
9where
10 E: Debug,
11{
12 #[error("authentication error: {0:?}")]
13 Authentication(HeaderValue),
14 #[error("xrpc response error: {0}")]
15 XrpcResponse(XrpcError<E>),
16 #[error("http request error: {0}")]
17 HttpRequest(#[from] http::Error),
18 #[error("http client error: {0}")]
19 HttpClient(Box<dyn std::error::Error + Send + Sync + 'static>),
20 #[error("serde_json error: {0}")]
21 SerdeJson(#[from] serde_json::Error),
22 #[error("serde_html_form error: {0}")]
23 SerdeHtmlForm(#[from] serde_html_form::ser::Error),
24 #[error("unexpected response type")]
25 UnexpectedResponseType,
26}
27
28pub type Result<T, E> = core::result::Result<T, Error<E>>;
30
31#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
41pub struct ErrorResponseBody {
42 pub error: Option<String>,
43 pub message: Option<String>,
44}
45
46impl Display for ErrorResponseBody {
47 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48 match (&self.error, &self.message) {
49 (Some(err), Some(msg)) => write!(f, "{err}: {msg}"),
50 (Some(err), None) | (None, Some(err)) => write!(f, "{err}"),
51 _ => Ok(()),
52 }
53 }
54}
55
56#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
60#[serde(untagged)]
61pub enum XrpcErrorKind<E> {
62 Custom(E),
63 Undefined(ErrorResponseBody),
64}
65
66impl<E: Display> Display for XrpcErrorKind<E> {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 match self {
69 Self::Custom(e) => Display::fmt(&e, f),
70 Self::Undefined(e) => Display::fmt(&e, f),
71 }
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct XrpcError<E> {
78 pub status: StatusCode,
79 pub error: Option<XrpcErrorKind<E>>,
80}
81
82impl<E: Display> Display for XrpcError<E> {
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 write!(f, "{}", self.status.as_str())?;
85 let Some(error) = &self.error else {
86 return Ok(());
87 };
88 let error = error.to_string();
89 if !error.is_empty() {
90 write!(f, " {error}")?;
91 }
92 Ok(())
93 }
94}