1use std::error;
4use std::fmt;
5
6use chrono::Duration;
7use serde::Deserialize;
8
9use crate::ErrorResponse;
10
11#[derive(Debug, Deserialize)]
13#[serde(rename_all = "snake_case")]
14pub enum ErrorType {
15 RequestError,
17 ApiError,
19}
20
21#[derive(Debug)]
23pub enum SignatureError {
24 Empty,
26 InvalidFormat,
28 InvalidPartFormat,
30 ParseError,
32 MaxVarianceExceeded(Duration),
34}
35
36impl fmt::Display for SignatureError {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 match self {
39 Self::Empty => write!(f, "empty string provided"),
40 Self::InvalidFormat => write!(f, "invalid format"),
41 Self::InvalidPartFormat => write!(f, "invalid signature part format"),
42 Self::ParseError => write!(f, "unable to extract timestamp or signature"),
43 Self::MaxVarianceExceeded(dur) => write!(f, "request was made more than {dur} ago"),
44 }
45 }
46}
47
48#[derive(Debug, Deserialize)]
50pub struct ValidationError {
51 pub field: String,
53 pub message: String,
55}
56
57#[derive(Debug, Deserialize)]
59pub struct PaddleApiError {
60 #[serde(rename = "type")]
62 pub error_type: ErrorType,
63 pub code: String,
65 pub detail: String,
67 pub documentation_url: String,
69 pub errors: Option<Vec<ValidationError>>,
71}
72
73#[derive(Debug)]
77pub enum Error {
78 Request(reqwest::Error),
79 Url(url::ParseError),
80 PaddleApi(ErrorResponse),
81 QueryString(serde_qs::Error),
82 PaddleSignature(SignatureError),
83 ParseIntError(std::num::ParseIntError),
84 MacError(hmac::digest::MacError),
85 JsonError(serde_json::Error),
86}
87
88impl fmt::Display for Error {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 match self {
91 Self::Request(err) => write!(f, "Request error: {}", err),
92 Self::Url(err) => write!(f, "URL error: {}", err),
93 Self::PaddleApi(err) => write!(f, "Paddle error: {}", err.error.detail),
94 Self::QueryString(err) => write!(f, "Query string error: {}", err),
95 Self::PaddleSignature(err) => write!(f, "Paddle signature error: {}", err),
96 Self::ParseIntError(err) => write!(f, "Integer parsing error: {}", err),
97 Self::MacError(err) => write!(f, "Hmac error: {}", err),
98 Self::JsonError(err) => write!(f, "Serde json error: {}", err),
99 }
100 }
101}
102
103impl error::Error for Error {
104 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
105 match self {
106 Self::Request(err) => Some(err),
107 Self::Url(err) => Some(err),
108 Self::PaddleApi(_) => None,
109 Self::QueryString(err) => Some(err),
110 Self::PaddleSignature(_) => None,
111 Self::ParseIntError(err) => Some(err),
112 Self::MacError(err) => Some(err),
113 Self::JsonError(err) => Some(err),
114 }
115 }
116}
117
118impl From<reqwest::Error> for Error {
119 fn from(err: reqwest::Error) -> Self {
120 Self::Request(err)
121 }
122}
123
124impl From<url::ParseError> for Error {
125 fn from(err: url::ParseError) -> Self {
126 Self::Url(err)
127 }
128}
129
130impl From<serde_qs::Error> for Error {
131 fn from(err: serde_qs::Error) -> Self {
132 Self::QueryString(err)
133 }
134}
135
136impl From<std::num::ParseIntError> for Error {
137 fn from(err: std::num::ParseIntError) -> Self {
138 Self::ParseIntError(err)
139 }
140}
141
142impl From<hmac::digest::MacError> for Error {
143 fn from(err: hmac::digest::MacError) -> Self {
144 Self::MacError(err)
145 }
146}
147
148impl From<serde_json::Error> for Error {
149 fn from(value: serde_json::Error) -> Self {
150 Self::JsonError(value)
151 }
152}