1use std::fmt;
6
7use serde::{
8 ser::{SerializeMap as _, Serializer},
9 Deserialize, Serialize,
10};
11
12mod account;
13mod authorization;
14mod challenge;
15mod directory;
16mod finalize;
17mod identifier;
18mod order;
19mod revocation;
20
21pub use self::{
22 account::Account,
23 authorization::{Authorization, AuthorizationStatus},
24 challenge::{Challenge, ChallengeStatus},
25 directory::{Directory, DirectoryMeta},
26 finalize::Finalize,
27 identifier::Identifier,
28 order::{Order, OrderStatus},
29 revocation::Revocation,
30};
31
32pub struct EmptyString;
34
35impl Serialize for EmptyString {
36 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
37 serializer.serialize_str("")
38 }
39}
40
41pub struct EmptyObject;
43
44impl Serialize for EmptyObject {
45 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
46 serializer.serialize_map(Some(0))?.end()
47 }
48}
49
50#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
51pub struct Problem {
52 #[serde(rename = "type")]
53 pub _type: String,
54
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub detail: Option<String>,
57
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub subproblems: Option<Vec<Subproblem>>,
60}
61
62impl Problem {
63 pub fn is_bad_nonce(&self) -> bool {
65 self._type == "badNonce"
66 }
67
68 pub fn is_jws_verification_error(&self) -> bool {
70 (self._type == "urn:ietf:params:acme:error:malformed"
71 || self._type == "urn:acme:error:malformed")
72 && self
73 .detail
74 .as_deref()
75 .is_some_and(|detail| detail == "JWS verification error")
76 }
77}
78
79impl fmt::Display for Problem {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match &self.detail {
82 Some(detail) => write!(f, "{}: {detail}", self._type),
83 _ => write!(f, "{}", self._type),
84 }
85 }
86}
87
88#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
89pub struct Subproblem {
90 #[serde(rename = "type")]
91 pub _type: String,
92 pub detail: Option<String>,
93 pub identifier: Option<identifier::Identifier>,
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_api_empty_string() {
102 let x = serde_json::to_string(&EmptyString).unwrap();
103 assert_eq!("\"\"", x);
104 }
105
106 #[test]
107 fn test_api_empty_object() {
108 let x = serde_json::to_string(&EmptyObject).unwrap();
109 assert_eq!("{}", x);
110 }
111}