blob_indexer/clients/
common.rs1use std::{fmt::Display, str::FromStr};
2
3use serde::Deserialize;
4
5#[derive(Clone, Debug, Deserialize)]
6#[serde(untagged)]
7pub enum NumericOrTextCode {
8 String(String),
9 Number(usize),
10}
11#[derive(Deserialize, Debug, Clone)]
13pub struct ErrorResponse {
14 pub code: NumericOrTextCode,
16 #[serde(default)]
18 pub message: Option<String>,
19}
20
21#[derive(Debug, thiserror::Error)]
22pub enum ClientError {
23 #[error(transparent)]
25 Reqwest(#[from] reqwest::Error),
26
27 #[error("API usage error: {0}")]
29 ApiError(ErrorResponse),
30
31 #[error(transparent)]
33 Other(#[from] anyhow::Error),
34
35 #[error("{0}")]
37 UrlParse(#[from] url::ParseError),
38
39 #[error("{0}")]
41 SerdeError(#[from] serde_json::Error),
42}
43
44#[derive(Deserialize, Debug, Clone)]
46#[serde(untagged)]
47pub enum ClientResponse<T> {
48 Error(ErrorResponse),
50 Success(T),
52 EmptySuccess,
54}
55
56pub type ClientResult<T> = Result<T, ClientError>;
57
58impl<T> ClientResponse<T> {
59 pub(crate) fn into_client_result(self) -> ClientResult<Option<T>> {
60 match self {
61 ClientResponse::Error(e) => Err(e.into()),
62 ClientResponse::Success(t) => Ok(Some(t)),
63 ClientResponse::EmptySuccess => Ok(None),
64 }
65 }
66
67 pub fn is_err(&self) -> bool {
69 matches!(self, Self::Error(_))
70 }
71}
72
73impl<T> FromStr for ClientResponse<T>
74where
75 T: serde::de::DeserializeOwned,
76{
77 type Err = serde_json::Error;
78
79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 if s.is_empty() {
81 return Ok(ClientResponse::EmptySuccess);
82 }
83 serde_json::from_str(s)
84 }
85}
86
87impl From<ErrorResponse> for ClientError {
88 fn from(err: ErrorResponse) -> Self {
89 Self::ApiError(err)
90 }
91}
92
93impl Display for NumericOrTextCode {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 match self {
96 Self::String(s) => f.write_str(s.to_string().as_ref()),
97 Self::Number(n) => f.write_str(n.to_string().as_ref()),
98 }
99 }
100}
101impl Display for ErrorResponse {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 f.write_str(&format!(
104 "Code: {}, Message: \"{}\"",
105 self.code,
106 self.message.as_deref().unwrap_or(""),
107 ))
108 }
109}