1use crate::pagination::Object;
3use serde::{Deserialize, Serialize};
4use std::fmt::{Display, Formatter};
5use std::num::NonZeroU16;
6
7#[derive(Debug, thiserror::Error)]
8pub enum Error {
9 #[error("Invalid NVD API Token: {}", source)]
10 InvalidApiToken {
11 source: reqwest::header::InvalidHeaderValue,
12 },
13
14 #[error("Unable to build reqwest HTTP client: {}", source)]
15 BuildingClient { source: reqwest::Error },
16
17 #[error("Error sending HTTP request: {}", source)]
18 RequestFailed {
19 #[from]
20 source: reqwest::Error,
21 },
22
23 #[error("Error reading response: {}", source)]
24 ResponseIo { source: reqwest::Error },
25
26 #[error("Error parsing json response: {}", source)]
27 JsonParse { source: serde_json::Error },
28
29 #[error("Unexpected API Response")]
30 UnexpectedResponse { response: Object },
31
32 #[error("API Error {}({}): {}", .error.code, .error.status, .error.message)]
33 Api { error: ErrorResponse },
34}
35
36#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
37#[serde(transparent)]
38pub struct StatusCode(NonZeroU16);
39
40impl Display for StatusCode {
41 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42 write!(f, "{}", self.0)
43 }
44}
45
46#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
47pub struct ErrorResponse {
48 pub status: StatusCode,
49 pub code: ErrorCode,
50 pub message: String,
51}
52
53#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
54#[serde(rename_all = "snake_case")]
55pub enum ErrorCode {
56 InvalidJson,
58 InvalidRequestUrl,
60 InvalidRequest,
62 MissionVersion,
64 Unauthorized,
66 RestrictedResource,
68 ObjectNotFound,
70 ConflictError,
72 RateLimited,
74 InternalServerError,
76 ServiceUnavailable,
78 #[serde(other)] Unknown,
80}
81
82impl Display for ErrorCode {
83 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84 write!(f, "{self:?}")
85 }
86}