1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::{any, error::Error};
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum BodyError {
#[error("URL encode error: {0}")]
UrlEncoded(#[from] serde_urlencoded::ser::Error),
#[error("JSON encode error: {0}")]
Json(#[from] serde_json::Error),
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ApiError<E>
where
E: Error + Send + Sync + 'static,
{
#[error("failed to create form data: {0}")]
Body(#[from] BodyError),
#[error("client error: {0}")]
Client(E),
#[error("failed to parse JSON: {0}")]
Json(#[from] serde_json::Error),
#[error("url parse error: {0}")]
Parse(#[from] url::ParseError),
#[error("Speedrun.com server error: {0}")]
SpeedrunApi(String),
#[error("Unknown speedrun.com server error: {0:?}")]
Unknown(serde_json::Value),
#[error("Parsing type {} from JSON: {}", typename, source)]
DataType {
source: serde_json::Error,
typename: &'static str,
},
#[error("Endpoint requires authentication, but no API key was provided")]
RequiresAuthentication,
}
impl<E> ApiError<E>
where
E: Error + Send + Sync + 'static,
{
pub fn client(source: E) -> Self {
Self::Client(source)
}
pub(crate) fn from_speedrun_api(val: serde_json::Value) -> Self {
if let Some(val) = val.pointer("/message") {
if let Some(msg) = val.as_str() {
Self::SpeedrunApi(msg.into())
} else {
Self::Unknown(val.clone())
}
} else {
Self::Unknown(val.clone())
}
}
pub(crate) fn data_type<T>(source: serde_json::Error) -> Self {
Self::DataType {
source,
typename: any::type_name::<T>(),
}
}
}