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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
use std::{
    error::Error,
    fmt::{Display, Formatter, Result},
    num::ParseIntError,
};

/// An error indicating that an xml element doesn't have an attribute that's marked as required in the schema
#[derive(Debug, Clone, PartialEq)]
pub struct MissingAttributeError {
    pub node_name: String,
    pub attr: &'static str,
}

impl MissingAttributeError {
    pub fn new<T: Into<String>>(node_name: T, attr: &'static str) -> Self {
        Self {
            node_name: node_name.into(),
            attr,
        }
    }
}

impl Display for MissingAttributeError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(
            f,
            "Xml element '{}' is missing a required attribute: {}",
            self.node_name, self.attr
        )
    }
}

impl Error for MissingAttributeError {
    fn description(&self) -> &str {
        "Missing required attribute"
    }
}

/// An error indicating that an xml element doesn't have a child node that's marked as required in the schema
#[derive(Debug, Clone, PartialEq)]
pub struct MissingChildNodeError {
    pub node_name: String,
    pub child_node: &'static str,
}

impl MissingChildNodeError {
    pub fn new<T: Into<String>>(node_name: T, child_node: &'static str) -> Self {
        Self {
            node_name: node_name.into(),
            child_node,
        }
    }
}

impl Display for MissingChildNodeError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(
            f,
            "Xml element '{}' is missing a required child element: {}",
            self.node_name, self.child_node
        )
    }
}

impl Error for MissingChildNodeError {
    fn description(&self) -> &str {
        "Xml element missing required child element"
    }
}

/// An error indicating that an xml element is not a member of a given element group
#[derive(Debug, Clone, PartialEq)]
pub struct NotGroupMemberError {
    node_name: String,
    group: &'static str,
}

impl NotGroupMemberError {
    pub fn new<T: Into<String>>(node_name: T, group: &'static str) -> Self {
        Self {
            node_name: node_name.into(),
            group,
        }
    }
}

impl Display for NotGroupMemberError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(
            f,
            "XmlNode '{}' is not a member of {} group",
            self.node_name, self.group
        )
    }
}

impl Error for NotGroupMemberError {
    fn description(&self) -> &str {
        "Xml element is not a group member error"
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MaxOccurs {
    Value(u32),
    Unbounded,
}

impl Display for MaxOccurs {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        match self {
            MaxOccurs::Value(val) => write!(f, "{}", val),
            MaxOccurs::Unbounded => write!(f, "unbounded"),
        }
    }
}

/// An error indicating that the xml element violates either minOccurs or maxOccurs of the schema
#[derive(Debug, Clone, PartialEq)]
pub struct LimitViolationError {
    node_name: String,
    violating_node_name: &'static str,
    min_occurs: u32,
    max_occurs: MaxOccurs,
    occurs: u32,
}

impl LimitViolationError {
    pub fn new<T: Into<String>>(
        node_name: T,
        violating_node_name: &'static str,
        min_occurs: u32,
        max_occurs: MaxOccurs,
        occurs: u32,
    ) -> Self {
        LimitViolationError {
            node_name: node_name.into(),
            violating_node_name,
            min_occurs,
            max_occurs,
            occurs,
        }
    }
}

impl Display for LimitViolationError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(
            f,
            "Element {} violates the limits of occurance in element: {}. minOccurs: {}, maxOccurs: {}, occurance: {}",
            self.node_name, self.violating_node_name, self.min_occurs, self.max_occurs, self.occurs,
        )
    }
}

impl Error for LimitViolationError {
    fn description(&self) -> &str {
        "Occurance limit violation"
    }
}

/// An error indicating that the parsed xml document is invalid
#[derive(Debug, Clone, Copy, Default)]
pub struct InvalidXmlError {}

impl Display for InvalidXmlError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "Invalid xml document")
    }
}

impl Error for InvalidXmlError {
    fn description(&self) -> &str {
        "Invalid xml error"
    }
}

/// Error indicating that an xml element's attribute is not a valid bool value
/// Valid bool values are: true, false, 0, 1
#[derive(Debug, Clone, PartialEq)]
pub struct ParseBoolError {
    pub attr_value: String,
}

impl ParseBoolError {
    pub fn new<T: Into<String>>(attr_value: T) -> Self {
        Self {
            attr_value: attr_value.into(),
        }
    }
}

impl Display for ParseBoolError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "Xml attribute is not a valid bool value: {}", self.attr_value)
    }
}

impl Error for ParseBoolError {
    fn description(&self) -> &str {
        "Xml attribute is not a valid bool value"
    }
}

/// Error indicating that a string cannot be converted to an enum type
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ParseEnumError {
    enum_name: &'static str,
}

impl ParseEnumError {
    pub fn new(enum_name: &'static str) -> Self {
        Self { enum_name }
    }
}

impl Display for ParseEnumError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "Cannot convert string to {}", self.enum_name)
    }
}

impl Error for ParseEnumError {
    fn description(&self) -> &str {
        "Cannot convert string to enum"
    }
}

/// Error indicating that parsing an AdjCoordinate or AdjAngle has failed
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AdjustParseError {}

impl Display for AdjustParseError {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "AdjCoordinate or AdjAngle parse error")
    }
}

impl Error for AdjustParseError {
    fn description(&self) -> &str {
        "Adjust parse error"
    }
}

/// Error indicating that parsing a str as HexColorRGB has failed
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseHexColorRGBError {
    Parse(ParseIntError),
    InvalidLength(StringLengthMismatch),
}

impl Display for ParseHexColorRGBError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match *self {
            ParseHexColorRGBError::Parse(ref err) => err.fmt(f),
            ParseHexColorRGBError::InvalidLength(ref mismatch) => write!(
                f,
                "length of string should be {} but {} is provided",
                mismatch.required, mismatch.provided
            ),
        }
    }
}

impl From<ParseIntError> for ParseHexColorRGBError {
    fn from(v: ParseIntError) -> Self {
        ParseHexColorRGBError::Parse(v)
    }
}

impl Error for ParseHexColorRGBError {}

/// Struct used to describe invalid length errors
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StringLengthMismatch {
    pub required: usize,
    pub provided: usize,
}

#[derive(Debug, Clone, PartialEq)]
pub enum PatternRestrictionError {
    NoMatch,
}

impl Display for PatternRestrictionError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "string doesn't match pattern")
    }
}

impl Error for PatternRestrictionError {}

#[derive(Debug, Clone, PartialEq)]
pub enum ParseHexColorError {
    Enum(ParseEnumError),
    HexColorRGB(ParseHexColorRGBError),
}

impl Display for ParseHexColorError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match *self {
            ParseHexColorError::Enum(ref e) => e.fmt(f),
            ParseHexColorError::HexColorRGB(ref e) => e.fmt(f),
        }
    }
}

impl Error for ParseHexColorError {}

impl From<ParseEnumError> for ParseHexColorError {
    fn from(v: ParseEnumError) -> Self {
        ParseHexColorError::Enum(v)
    }
}

impl From<ParseHexColorRGBError> for ParseHexColorError {
    fn from(v: ParseHexColorRGBError) -> Self {
        ParseHexColorError::HexColorRGB(v)
    }
}