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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
use std::borrow::Cow;
use crate::fault::Fault;
#[derive(Debug, PartialEq, thiserror::Error)]
#[non_exhaustive]
/// Error type representing conversion errors between XML-RPC values and Rust values.
pub enum Error {
/// Error variant for XML parser errors.
#[error("Failed to parse XML data: {}", .error)]
InvalidData {
/// description of the parsing error
error: String,
},
/// Error variant for invalid dateTime.iso8601 values.
#[error("Invalid format for dateTime.iso8601 value: \n{}", .error)]
InvalidDateTime {
/// description of the parsing error
error: String,
},
/// Error variant for a missing struct field.
#[error("Struct '{}' missing field: {}", .name, .field)]
MissingField {
/// name of the struct that has a missing field
name: Cow<'static, str>,
/// name of the missing struct field
field: Cow<'static, str>,
},
#[error("Parameter mismatch: got {} values, expected {}", .argument, .expected)]
/// Error variant for mismatch with an expected number of values.
ParameterMismatch {
/// number of received values
argument: usize,
/// number of expected values
expected: usize,
},
/// Error variant for mismatch with an expected value type.
#[error("Type mismatch: got {}, expected {}", .argument, .expected)]
WrongType {
/// mismatched input type
argument: Cow<'static, str>,
/// expected input type
expected: Cow<'static, str>,
},
}
impl Error {
/// Construct a [`Error`] for invalid input data.
#[must_use]
pub const fn invalid_data(error: String) -> Error {
Error::InvalidData { error }
}
/// Check if a given [`Error`] was raised for invalid data.
#[must_use]
pub const fn is_invalid_data(&self) -> bool {
matches!(self, Error::InvalidData { .. })
}
/// Check for [`Error::InvalidData`] and return the inner error in case of a match.
///
/// The returned string describes the XML (de)serialization issue.
#[must_use]
pub fn as_invalid_data(&self) -> Option<&str> {
if let Error::InvalidData { error } = self {
Some(error)
} else {
None
}
}
/// Construct an [`Error`] for invalid datetime values.
#[must_use]
pub const fn invalid_datetime(error: String) -> Error {
Error::InvalidDateTime { error }
}
/// Check if a given [`Error`] was raised for an invalid datetime value.
#[must_use]
pub const fn is_invalid_datetime(&self) -> bool {
matches!(self, Error::InvalidDateTime { .. })
}
/// Check for [`Error::InvalidDateTime`] and return the inner error in case of a match.
///
/// The returned string describes the parsing failure.
#[must_use]
pub fn as_invalid_datetime(&self) -> Option<&str> {
if let Error::InvalidDateTime { error } = self {
Some(error)
} else {
None
}
}
/// Construct a [`Error`] for a missing struct field.
#[must_use]
pub const fn missing_field(name: &'static str, field: &'static str) -> Error {
Error::MissingField {
name: Cow::Borrowed(name),
field: Cow::Borrowed(field),
}
}
/// Check if a given [`Error`] was raised for a missing struct field.
#[must_use]
pub const fn is_missing_field(&self) -> bool {
matches!(self, Error::MissingField { .. })
}
/// Check for [`Error::MissingField`] and return the inner error in case of a match.
///
/// The returned value is a tuple of (struct name, missing field name).
#[must_use]
pub fn as_missing_field(&self) -> Option<(&str, &str)> {
if let Error::MissingField { name, field } = self {
Some((name, field))
} else {
None
}
}
/// Construct a [`Error`] for a parameter number mismatch.
#[must_use]
pub const fn parameter_mismatch(argument: usize, expected: usize) -> Error {
Error::ParameterMismatch { argument, expected }
}
/// Check if a given [`Error`] was raised for unexpected number of return values.
#[must_use]
pub const fn is_parameter_mismatch(&self) -> bool {
matches!(self, Error::ParameterMismatch { .. })
}
/// Check for [`Error::ParameterMismatch`] and return the inner error in case of a match.
///
/// The returned value is a tuple of the numbers of (received arguments, expected arguments).
#[must_use]
pub const fn as_parameter_mismatch(&self) -> Option<(usize, usize)> {
if let Error::ParameterMismatch { argument, expected } = self {
Some((*argument, *expected))
} else {
None
}
}
/// Construct a [`Error`] for a type mismatch.
#[must_use]
pub const fn wrong_type(argument: &'static str, expected: &'static str) -> Error {
Error::WrongType {
argument: Cow::Borrowed(argument),
expected: Cow::Borrowed(expected),
}
}
/// Check if a given [`Error`] was raised for a type mismatch.
#[must_use]
pub const fn is_wrong_type(&self) -> bool {
matches!(self, Error::WrongType { .. })
}
/// Check for [`Error::WrongType`] and return the inner error in case of a match.
///
/// The returned value is a tuple of the names of (received type, expected type).
#[must_use]
pub fn as_wrong_type(&self) -> Option<(&str, &str)> {
if let Error::WrongType { argument, expected } = self {
Some((argument, expected))
} else {
None
}
}
}
impl From<Error> for Fault {
fn from(error: Error) -> Self {
Fault::new(400, error.to_string())
}
}