1use std::borrow::Cow;
2use std::str::FromStr;
3
4use crate::error::{BinaryError, Result};
5use crate::jid::Jid;
6use crate::node::{Attrs, Node, NodeRef, NodeStr, NodeValue, ValueRef};
7
8pub struct AttrParser<'a> {
9 pub attrs: &'a Attrs,
10 pub errors: Vec<BinaryError>,
11}
12
13pub struct AttrParserRef<'a> {
14 pub(crate) attrs: &'a [(NodeStr<'a>, 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.attrs.iter().find(|(k, _)| **k == *key).map(|(_, v)| v);
40
41 if require && val.is_none() {
42 self.errors.push(BinaryError::AttrParse(format!(
43 "Required attribute '{key}' not found"
44 )));
45 }
46
47 val
48 }
49
50 pub fn optional_string(&mut self, key: &str) -> Option<Cow<'a, str>> {
54 self.get_raw(key, false).map(|v| v.as_str())
55 }
56
57 pub fn required_string(&mut self, key: &str) -> Result<Cow<'a, str>> {
62 self.optional_string(key)
63 .ok_or_else(|| BinaryError::MissingAttr(key.to_string()))
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.as_str())
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 NodeValue> {
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 fn get_string_value(&mut self, key: &str, require: bool) -> Option<Cow<'a, str>> {
194 self.get_raw(key, require).map(|v| match v {
195 NodeValue::String(s) => Cow::Borrowed(s.as_str()),
196 NodeValue::Jid(j) => Cow::Owned(j.to_string()),
197 })
198 }
199
200 pub fn optional_string(&mut self, key: &str) -> Option<Cow<'a, str>> {
205 self.get_raw(key, false).map(|v| v.as_str())
206 }
207
208 pub fn required_string(&mut self, key: &str) -> Result<Cow<'a, str>> {
213 self.optional_string(key)
214 .ok_or_else(|| BinaryError::MissingAttr(key.to_string()))
215 }
216
217 pub fn optional_jid(&mut self, key: &str) -> Option<Jid> {
222 self.get_raw(key, false).and_then(|v| match v {
223 NodeValue::Jid(j) => Some(j.clone()),
224 NodeValue::String(s) => match Jid::from_str(s) {
225 Ok(jid) => Some(jid),
226 Err(e) => {
227 self.errors.push(BinaryError::from(e));
228 None
229 }
230 },
231 })
232 }
233
234 pub fn jid(&mut self, key: &str) -> Jid {
235 self.get_raw(key, true); self.optional_jid(key).unwrap_or_default()
237 }
238
239 pub fn non_ad_jid(&mut self, key: &str) -> Jid {
240 self.jid(key).to_non_ad()
241 }
242
243 fn get_bool(&mut self, key: &str, require: bool) -> Option<bool> {
245 self.get_string_value(key, require)
246 .and_then(|s| match s.parse::<bool>() {
247 Ok(val) => Some(val),
248 Err(e) => {
249 self.errors.push(BinaryError::AttrParse(format!(
250 "Failed to parse bool from '{s}' for key '{key}': {e}"
251 )));
252 None
253 }
254 })
255 }
256
257 pub fn optional_bool(&mut self, key: &str) -> bool {
258 self.get_bool(key, false).unwrap_or(false)
259 }
260
261 pub fn bool(&mut self, key: &str) -> bool {
262 self.get_bool(key, true).unwrap_or(false)
263 }
264
265 pub fn optional_u64(&mut self, key: &str) -> Option<u64> {
267 self.get_string_value(key, false)
268 .and_then(|s| match s.parse::<u64>() {
269 Ok(val) => Some(val),
270 Err(e) => {
271 self.errors.push(BinaryError::AttrParse(format!(
272 "Failed to parse u64 from '{s}' for key '{key}': {e}"
273 )));
274 None
275 }
276 })
277 }
278
279 pub fn unix_time(&mut self, key: &str) -> i64 {
280 self.get_raw(key, true);
281 self.optional_unix_time(key).unwrap_or_default()
282 }
283
284 pub fn optional_unix_time(&mut self, key: &str) -> Option<i64> {
285 self.get_i64(key, false)
286 }
287
288 pub fn unix_milli(&mut self, key: &str) -> i64 {
289 self.get_raw(key, true);
290 self.optional_unix_milli(key).unwrap_or_default()
291 }
292
293 pub fn optional_unix_milli(&mut self, key: &str) -> Option<i64> {
294 self.get_i64(key, false)
295 }
296
297 fn get_i64(&mut self, key: &str, require: bool) -> Option<i64> {
298 self.get_string_value(key, require)
299 .and_then(|s| match s.parse::<i64>() {
300 Ok(val) => Some(val),
301 Err(e) => {
302 self.errors.push(BinaryError::AttrParse(format!(
303 "Failed to parse i64 from '{s}' for key '{key}': {e}"
304 )));
305 None
306 }
307 })
308 }
309}