1use std::borrow::Cow;
2use std::str::FromStr;
3
4use crate::error::{BinaryError, Result};
5use crate::jid::Jid;
6use crate::node::{Attrs, Node, NodeRef, ValueRef};
7
8pub struct AttrParser<'a> {
9 pub attrs: &'a Attrs,
10 pub errors: Vec<BinaryError>,
11}
12
13pub struct AttrParserRef<'a> {
14 pub attrs: &'a [(Cow<'a, str>, ValueRef<'a>)],
15 pub errors: Vec<BinaryError>,
16}
17
18impl<'a> AttrParserRef<'a> {
19 pub fn new(node: &'a NodeRef<'a>) -> Self {
20 Self {
21 attrs: node.attrs.as_slice(),
22 errors: Vec::new(),
23 }
24 }
25
26 pub fn ok(&self) -> bool {
27 self.errors.is_empty()
28 }
29
30 pub fn finish(&self) -> Result<()> {
31 if self.ok() {
32 Ok(())
33 } else {
34 Err(BinaryError::AttrList(self.errors.clone()))
35 }
36 }
37
38 fn get_raw(&mut self, key: &str, require: bool) -> Option<&'a ValueRef<'a>> {
39 let val = self
40 .attrs
41 .iter()
42 .find(|(k, _)| k.as_ref() == key)
43 .map(|(_, v)| v);
44
45 if require && val.is_none() {
46 self.errors.push(BinaryError::AttrParse(format!(
47 "Required attribute '{key}' not found"
48 )));
49 }
50
51 val
52 }
53
54 pub fn optional_string(&mut self, key: &str) -> Option<&'a str> {
57 self.get_raw(key, false).and_then(|v| v.as_str())
58 }
59
60 pub fn string(&mut self, key: &str) -> String {
61 self.get_raw(key, true)
62 .map(|v| v.to_string_cow().into_owned())
63 .unwrap_or_default()
64 }
65
66 pub fn optional_jid(&mut self, key: &str) -> Option<Jid> {
70 self.get_raw(key, false).and_then(|v| match v.to_jid() {
71 Some(jid) => Some(jid),
72 None => {
73 if let ValueRef::String(s) = v {
75 self.errors
76 .push(BinaryError::AttrParse(format!("Invalid JID: {s}")));
77 }
78 None
79 }
80 })
81 }
82
83 pub fn jid(&mut self, key: &str) -> Jid {
84 self.get_raw(key, true);
85 self.optional_jid(key).unwrap_or_default()
86 }
87
88 pub fn non_ad_jid(&mut self, key: &str) -> Jid {
89 self.jid(key).to_non_ad()
90 }
91
92 fn get_string_value(&mut self, key: &str, require: bool) -> Option<Cow<'a, str>> {
93 self.get_raw(key, require).map(|v| v.to_string_cow())
94 }
95
96 fn get_bool(&mut self, key: &str, require: bool) -> Option<bool> {
97 self.get_string_value(key, require)
98 .and_then(|s| match s.parse::<bool>() {
99 Ok(val) => Some(val),
100 Err(e) => {
101 self.errors.push(BinaryError::AttrParse(format!(
102 "Failed to parse bool from '{s}' for key '{key}': {e}"
103 )));
104 None
105 }
106 })
107 }
108
109 pub fn optional_bool(&mut self, key: &str) -> bool {
110 self.get_bool(key, false).unwrap_or(false)
111 }
112
113 pub fn bool(&mut self, key: &str) -> bool {
114 self.get_bool(key, true).unwrap_or(false)
115 }
116
117 pub fn optional_u64(&mut self, key: &str) -> Option<u64> {
118 self.get_string_value(key, false)
119 .and_then(|s| match s.parse::<u64>() {
120 Ok(val) => Some(val),
121 Err(e) => {
122 self.errors.push(BinaryError::AttrParse(format!(
123 "Failed to parse u64 from '{s}' for key '{key}': {e}"
124 )));
125 None
126 }
127 })
128 }
129
130 pub fn unix_time(&mut self, key: &str) -> i64 {
131 self.get_raw(key, true);
132 self.optional_unix_time(key).unwrap_or_default()
133 }
134
135 pub fn optional_unix_time(&mut self, key: &str) -> Option<i64> {
136 self.get_i64(key, false)
137 }
138
139 pub fn unix_milli(&mut self, key: &str) -> i64 {
140 self.get_raw(key, true);
141 self.optional_unix_milli(key).unwrap_or_default()
142 }
143
144 pub fn optional_unix_milli(&mut self, key: &str) -> Option<i64> {
145 self.get_i64(key, false)
146 }
147
148 fn get_i64(&mut self, key: &str, require: bool) -> Option<i64> {
149 self.get_string_value(key, require)
150 .and_then(|s| match s.parse::<i64>() {
151 Ok(val) => Some(val),
152 Err(e) => {
153 self.errors.push(BinaryError::AttrParse(format!(
154 "Failed to parse i64 from '{s}' for key '{key}': {e}"
155 )));
156 None
157 }
158 })
159 }
160}
161
162impl<'a> AttrParser<'a> {
163 pub fn new(node: &'a Node) -> Self {
164 Self {
165 attrs: &node.attrs,
166 errors: Vec::new(),
167 }
168 }
169
170 pub fn ok(&self) -> bool {
171 self.errors.is_empty()
172 }
173
174 pub fn finish(&self) -> Result<()> {
175 if self.ok() {
176 Ok(())
177 } else {
178 Err(BinaryError::AttrList(self.errors.clone()))
179 }
180 }
181
182 fn get_raw(&mut self, key: &str, require: bool) -> Option<&'a String> {
183 let val = self.attrs.get(key);
184 if require && val.is_none() {
185 self.errors.push(BinaryError::AttrParse(format!(
186 "Required attribute '{key}' not found"
187 )));
188 }
189 val
190 }
191
192 pub fn optional_string(&mut self, key: &str) -> Option<&'a str> {
194 self.get_raw(key, false).map(|s| s.as_str())
195 }
196
197 pub fn string(&mut self, key: &str) -> String {
198 self.get_raw(key, true).cloned().unwrap_or_default()
199 }
200
201 pub fn optional_jid(&mut self, key: &str) -> Option<Jid> {
203 self.get_raw(key, false)
204 .and_then(|s| match Jid::from_str(s) {
205 Ok(jid) => Some(jid),
206 Err(e) => {
207 self.errors.push(BinaryError::from(e));
208 None
209 }
210 })
211 }
212
213 pub fn jid(&mut self, key: &str) -> Jid {
214 self.get_raw(key, true); self.optional_jid(key).unwrap_or_default()
216 }
217
218 pub fn non_ad_jid(&mut self, key: &str) -> Jid {
219 self.jid(key).to_non_ad()
220 }
221
222 fn get_bool(&mut self, key: &str, require: bool) -> Option<bool> {
224 self.get_raw(key, require)
225 .and_then(|s| match s.parse::<bool>() {
226 Ok(val) => Some(val),
227 Err(e) => {
228 self.errors.push(BinaryError::AttrParse(format!(
229 "Failed to parse bool from '{s}' for key '{key}': {e}"
230 )));
231 None
232 }
233 })
234 }
235
236 pub fn optional_bool(&mut self, key: &str) -> bool {
237 self.get_bool(key, false).unwrap_or(false)
238 }
239
240 pub fn bool(&mut self, key: &str) -> bool {
241 self.get_bool(key, true).unwrap_or(false)
242 }
243
244 pub fn optional_u64(&mut self, key: &str) -> Option<u64> {
246 self.get_raw(key, false)
247 .and_then(|s| match s.parse::<u64>() {
248 Ok(val) => Some(val),
249 Err(e) => {
250 self.errors.push(BinaryError::AttrParse(format!(
251 "Failed to parse u64 from '{s}' for key '{key}': {e}"
252 )));
253 None
254 }
255 })
256 }
257
258 pub fn unix_time(&mut self, key: &str) -> i64 {
259 self.get_raw(key, true);
260 self.optional_unix_time(key).unwrap_or_default()
261 }
262
263 pub fn optional_unix_time(&mut self, key: &str) -> Option<i64> {
264 self.get_i64(key, false)
265 }
266
267 pub fn unix_milli(&mut self, key: &str) -> i64 {
268 self.get_raw(key, true);
269 self.optional_unix_milli(key).unwrap_or_default()
270 }
271
272 pub fn optional_unix_milli(&mut self, key: &str) -> Option<i64> {
273 self.get_i64(key, false)
274 }
275
276 fn get_i64(&mut self, key: &str, require: bool) -> Option<i64> {
277 self.get_raw(key, require)
278 .and_then(|s| match s.parse::<i64>() {
279 Ok(val) => Some(val),
280 Err(e) => {
281 self.errors.push(BinaryError::AttrParse(format!(
282 "Failed to parse i64 from '{s}' for key '{key}': {e}"
283 )));
284 None
285 }
286 })
287 }
288}