1use std::{
2 num::{ParseFloatError, ParseIntError},
3 ops::Range,
4 str::ParseBoolError,
5};
6
7use chrono::ParseError;
8use roxmltree::Node;
9use thiserror::Error;
10
11#[derive(Error, Debug, Clone)]
12pub enum XmlErrorInner {
14 #[error("Failed to load XML: {0}")]
15 Xml(#[from] roxmltree::Error),
17 #[error("Expected child: {0}")]
18 MissingField(String),
20 #[error("Expected attribute: {0}")]
21 MissingAttribute(String),
23 #[error("Failed to parse {0} as integer.")]
24 ParseInt(String, ParseIntError),
26 #[error("Failed to parse {0} as float.")]
27 ParseFloat(String, ParseFloatError),
29 #[error("Failed to parse {0} as bool.")]
30 ParseBool(String, ParseBoolError),
32 #[error("Missing node content")]
33 MissingContent,
35 #[error("Invalid timestamp for {0}: {1}")]
36 ParseDateTime(String, ParseError),
38 #[error("Invalid UUID for {0}: {1}")]
39 ParseUuid(String, uuid::Error),
41 #[error("{0}")]
42 Other(String),
44}
45
46#[derive(Error, Debug, Clone)]
47#[error("{error} at {span:?}")]
48pub struct XmlError {
50 pub span: Range<usize>,
52 pub error: XmlErrorInner,
54}
55
56impl From<roxmltree::Error> for XmlError {
57 fn from(value: roxmltree::Error) -> Self {
58 Self {
59 span: 0..0,
60 error: XmlErrorInner::Xml(value),
61 }
62 }
63}
64
65impl XmlError {
66 pub fn missing_field(node: &Node<'_, '_>, name: &str) -> Self {
68 Self {
69 span: node.range(),
70 error: XmlErrorInner::MissingField(name.to_owned()),
71 }
72 }
73
74 pub fn missing_attribute(node: &Node<'_, '_>, name: &str) -> Self {
76 Self {
77 span: node.range(),
78 error: XmlErrorInner::MissingAttribute(name.to_owned()),
79 }
80 }
81
82 pub fn other(node: &Node<'_, '_>, info: &str) -> Self {
84 Self {
85 span: node.range(),
86 error: XmlErrorInner::Other(info.to_owned()),
87 }
88 }
89
90 pub fn parse_int(node: &Node<'_, '_>, attr: &str, err: ParseIntError) -> Self {
92 Self {
93 span: node.range(),
94 error: XmlErrorInner::ParseInt(attr.to_owned(), err),
95 }
96 }
97
98 pub fn parse_float(node: &Node<'_, '_>, attr: &str, err: ParseFloatError) -> Self {
100 Self {
101 span: node.range(),
102 error: XmlErrorInner::ParseFloat(attr.to_owned(), err),
103 }
104 }
105
106 pub fn parse_bool(node: &Node<'_, '_>, attr: &str, err: ParseBoolError) -> Self {
108 Self {
109 span: node.range(),
110 error: XmlErrorInner::ParseBool(attr.to_owned(), err),
111 }
112 }
113
114 pub fn parse_date_time(node: &Node<'_, '_>, attr: &str, err: ParseError) -> Self {
116 Self {
117 span: node.range(),
118 error: XmlErrorInner::ParseDateTime(attr.to_owned(), err),
119 }
120 }
121
122 pub fn parse_uuid(node: &Node<'_, '_>, attr: &str, err: uuid::Error) -> Self {
124 Self {
125 span: node.range(),
126 error: XmlErrorInner::ParseUuid(attr.to_owned(), err),
127 }
128 }
129
130 pub fn missing_content(node: &Node<'_, '_>) -> Self {
132 Self {
133 span: node.range(),
134 error: XmlErrorInner::MissingContent,
135 }
136 }
137}