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
use std::borrow::Cow;
use thiserror::Error;
use crate::fault::Fault;
#[derive(Debug, Error)]
/// error type used for conversion errors between XML-RPC values and Rust values
pub enum DxrError {
/// error variant describing XML parser errors
#[error("Failed to parse XML data: {}", .error)]
InvalidData {
/// description of the parsing error
error: String,
},
/// error variant describing 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 describing value number mismatch
ParameterMismatch {
/// number of received values
argument: usize,
/// number of expected values
expected: usize,
},
/// error variant describing a type mismatch between XML-RPC value and a Rust struct field
#[error("Type mismatch: got {}, expected {}", .argument, .expected)]
WrongType {
/// mismatched input type
argument: Cow<'static, str>,
/// expected input type
expected: Cow<'static, str>,
},
}
impl DxrError {
/// construct a [`DxrError`] for invalid input data
pub fn invalid_data(error: String) -> DxrError {
DxrError::InvalidData { error }
}
/// check if a given [`DxrError`] was raised for invalid data
pub fn is_invalid_data(&self) -> bool {
matches!(self, DxrError::InvalidData { .. })
}
/// check for [`DxrError::InvalidData`] and return the inner error in case of a match
///
/// The returned string describes the XML (de)serialization issue.
pub fn as_invalid_data(&self) -> Option<&str> {
if let DxrError::InvalidData { error } = self {
Some(error)
} else {
None
}
}
/// construct a [`DxrError`] for a missing struct field
pub fn missing_field(name: &'static str, field: &'static str) -> DxrError {
DxrError::MissingField {
name: Cow::Borrowed(name),
field: Cow::Borrowed(field),
}
}
/// check if a given [`DxrError`] was raised for a missing struct field
pub fn is_missing_field(&self) -> bool {
matches!(self, DxrError::MissingField { .. })
}
/// check for [`DxrError::MissingField`] and return the inner error in case of a match
///
/// The returned value is a tuple of (struct name, missing field name).
pub fn as_missing_field(&self) -> Option<(&str, &str)> {
if let DxrError::MissingField { name, field } = self {
Some((name, field))
} else {
None
}
}
/// construct a [`DxrError`] for a parameter number mismatch
pub fn parameter_mismatch(argument: usize, expected: usize) -> DxrError {
DxrError::ParameterMismatch { argument, expected }
}
/// check if a given [`DxrError`] was raised for unexpected number of return values
pub fn is_parameter_mismatch(&self) -> bool {
matches!(self, DxrError::ParameterMismatch { .. })
}
/// check for [`DxrError::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).
pub fn as_parameter_mismatch(&self) -> Option<(usize, usize)> {
if let DxrError::ParameterMismatch { argument, expected } = self {
Some((*argument, *expected))
} else {
None
}
}
/// construct a [`DxrError`] for a type mismatch
pub fn wrong_type(argument: &'static str, expected: &'static str) -> DxrError {
DxrError::WrongType {
argument: Cow::Borrowed(argument),
expected: Cow::Borrowed(expected),
}
}
/// check if a given [`DxrError`] was raised for a type mismatch
pub fn is_wrong_type(&self) -> bool {
matches!(self, DxrError::WrongType { .. })
}
/// check for [`DxrError::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).
pub fn as_wrong_type(&self) -> Option<(&str, &str)> {
if let DxrError::WrongType { argument, expected } = self {
Some((argument, expected))
} else {
None
}
}
}
impl From<DxrError> for Fault {
fn from(error: DxrError) -> Self {
match error {
DxrError::InvalidData { .. } => Fault::new(400, error.to_string()),
DxrError::MissingField { .. } => Fault::new(400, error.to_string()),
DxrError::ParameterMismatch { .. } => Fault::new(400, error.to_string()),
DxrError::WrongType { .. } => Fault::new(400, error.to_string()),
}
}
}