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