1use error::ParseTarget;
4pub use error::{CrawlerError, CrawlerResult};
5pub use iter::*;
6use serde::de::DeserializeOwned;
7use serde::Deserialize;
8#[doc(no_inline)]
12pub use serde_json::Value;
13use std::fmt::Display;
14use std::ops::ControlFlow;
15use std::str::FromStr;
16use std::sync::Arc;
17
18mod error;
19mod iter;
20
21pub trait JsonCrawler
24where
25 Self: Sized,
26{
27 type BorrowTo<'a>: JsonCrawler
28 where
29 Self: 'a;
30 type IterMut<'a>: JsonCrawlerIterator<Item = Self::BorrowTo<'a>>
31 where
32 Self: 'a;
33 type IntoIter: JsonCrawlerIterator<Item = Self>;
34 fn navigate_pointer(self, new_path: impl AsRef<str>) -> CrawlerResult<Self>;
35 fn navigate_index(self, index: usize) -> CrawlerResult<Self>;
36 fn borrow_pointer(&mut self, path: impl AsRef<str>) -> CrawlerResult<Self::BorrowTo<'_>>;
37 fn borrow_index(&mut self, index: usize) -> CrawlerResult<Self::BorrowTo<'_>>;
38 fn borrow_mut(&mut self) -> Self::BorrowTo<'_>;
39 fn try_into_iter(self) -> CrawlerResult<Self::IntoIter>;
40 fn try_iter_mut(&mut self) -> CrawlerResult<Self::IterMut<'_>>;
41 fn path_exists(&self, path: &str) -> bool;
42 fn get_path(&self) -> String;
43 fn get_source(&self) -> Arc<String>;
44 fn take_value<T: DeserializeOwned>(&mut self) -> CrawlerResult<T>;
45 fn take_value_pointer<T: DeserializeOwned>(
46 &mut self,
47 path: impl AsRef<str>,
48 ) -> CrawlerResult<T>;
49 fn borrow_value<T: for<'de> Deserialize<'de>>(&self) -> CrawlerResult<T>;
50 fn borrow_value_pointer<T: for<'de> Deserialize<'de>>(
51 &self,
52 path: impl AsRef<str>,
53 ) -> CrawlerResult<T>;
54 fn take_value_pointers<T: DeserializeOwned, S: AsRef<str>>(
66 &mut self,
67 paths: &[S],
68 ) -> CrawlerResult<T>;
69 fn try_expect<F, O>(&mut self, msg: impl ToString, f: F) -> CrawlerResult<O>
90 where
91 F: FnOnce(&mut Self) -> CrawlerResult<Option<O>>,
92 {
93 match f(self) {
94 Ok(Some(r)) => Ok(r),
95 Ok(None) => Err(CrawlerError::parsing(
96 self.get_path(),
97 self.get_source(),
98 crate::error::ParseTarget::Other(std::any::type_name::<O>().to_string()),
99 Some(msg.to_string()),
100 )),
101 Err(e) => {
103 let msg = format!("Expected {} but encountered '{e}'", msg.to_string());
104 Err(CrawlerError::parsing(
105 self.get_path(),
106 self.get_source(),
107 crate::error::ParseTarget::Other(std::any::type_name::<O>().to_string()),
108 Some(msg),
109 ))
110 }
111 }
112 }
113 fn take_and_parse_str<F: FromStr>(&mut self) -> CrawlerResult<F>
116 where
117 F::Err: Display,
118 {
119 let as_string = self.take_value::<String>()?;
120 str::parse::<F>(as_string.as_str()).map_err(|e| {
121 CrawlerError::parsing(
122 self.get_path(),
123 self.get_source(),
124 crate::error::ParseTarget::Other(std::any::type_name::<F>().to_string()),
125 Some(format!("{e}")),
126 )
127 })
128 }
129 fn try_functions<O>(
137 &mut self,
138 functions: impl IntoIterator<Item = fn(&mut Self) -> CrawlerResult<O>>,
139 ) -> CrawlerResult<O> {
140 let original_path = self.get_path();
141 let source_ptr = self.get_source();
142 let output = functions.into_iter().try_fold(Vec::new(), |mut acc, f| {
143 let res = f(self);
144 let e = match res {
145 Ok(ret) => return ControlFlow::Break(ret),
146 Err(e) => e,
147 };
148 acc.push(e);
149 ControlFlow::Continue(acc)
150 });
151 match output {
152 ControlFlow::Continue(c) => Err(CrawlerError::multiple_parse_error(
153 original_path,
154 source_ptr,
155 c,
156 )),
157 ControlFlow::Break(b) => Ok(b),
158 }
159 }
160 fn apply_function_at_paths<O>(
168 &mut self,
169 paths: &[impl AsRef<str>],
170 function: fn(Self::BorrowTo<'_>) -> O,
171 ) -> CrawlerResult<O> {
172 let output = paths
173 .iter()
174 .find_map(|path| self.borrow_pointer(path.as_ref()).ok().map(function));
175 match output {
176 None => Err(CrawlerError::paths_not_found(
177 self.get_path(),
178 self.get_source(),
179 paths.iter().map(|s| s.as_ref().to_string()).collect(),
180 )),
181 Some(o) => Ok(o),
182 }
183 }
184}
185
186#[derive(Clone, PartialEq, Debug)]
187pub struct JsonCrawlerOwned {
188 source: Arc<String>,
191 crawler: serde_json::Value,
192 path: PathList,
193}
194pub struct JsonCrawlerBorrowed<'a> {
195 source: Arc<String>,
198 crawler: &'a mut serde_json::Value,
199 path: PathList,
200}
201
202impl JsonCrawlerOwned {
203 pub fn new(source: String, json: serde_json::Value) -> Self {
208 Self {
209 source: Arc::new(source),
210 crawler: json,
211 path: Default::default(),
212 }
213 }
214}
215
216impl<'a> JsonCrawler for JsonCrawlerBorrowed<'a> {
217 type BorrowTo<'b>
218 = JsonCrawlerBorrowed<'b>
219 where
220 Self: 'b;
221 type IterMut<'b>
222 = JsonCrawlerArrayIterMut<'b>
223 where
224 Self: 'b;
225 type IntoIter = JsonCrawlerArrayIterMut<'a>;
226 fn take_value_pointer<T: DeserializeOwned>(
227 &mut self,
228 path: impl AsRef<str>,
229 ) -> CrawlerResult<T> {
230 let mut path_clone = self.path.clone();
231 path_clone.push(JsonPath::pointer(path.as_ref()));
232 serde_json::from_value(
233 self.crawler
234 .pointer_mut(path.as_ref())
235 .map(|v| v.take())
236 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?,
237 )
238 .map_err(|e| {
239 CrawlerError::parsing(
240 &path_clone,
241 self.source.clone(),
242 ParseTarget::Other(std::any::type_name::<T>().to_string()),
243 Some(format!("{e}")),
244 )
245 })
246 }
247 fn borrow_pointer(&mut self, path: impl AsRef<str>) -> CrawlerResult<Self::BorrowTo<'_>> {
248 let mut path_clone = self.path.clone();
249 path_clone.push(JsonPath::pointer(path.as_ref()));
250 let crawler = self
251 .crawler
252 .pointer_mut(path.as_ref())
253 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?;
254 Ok(JsonCrawlerBorrowed {
255 source: self.source.clone(),
256 crawler,
257 path: path_clone,
258 })
259 }
260 fn navigate_pointer(self, path: impl AsRef<str>) -> CrawlerResult<Self> {
261 let mut path_clone = self.path.clone();
262 path_clone.push(JsonPath::pointer(path.as_ref()));
263 let crawler = self
264 .crawler
265 .pointer_mut(path.as_ref())
266 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?;
267 Ok(Self {
268 source: self.source,
269 crawler,
270 path: path_clone,
271 })
272 }
273 fn try_into_iter(self) -> CrawlerResult<Self::IntoIter> {
274 let json_array = self.crawler.as_array_mut().ok_or_else(|| {
275 CrawlerError::parsing(&self.path, self.source.clone(), ParseTarget::Array, None)
276 })?;
277 let path_clone = self.path.clone();
278 let cur_back = json_array.len().saturating_sub(1);
279 Ok(JsonCrawlerArrayIterMut {
280 source: self.source,
281 array: json_array.iter_mut(),
282 path: path_clone,
283 cur_front: 0,
284 cur_back,
285 })
286 }
287 fn try_iter_mut(&mut self) -> CrawlerResult<Self::IterMut<'_>> {
288 let json_array = self.crawler.as_array_mut().ok_or_else(|| {
289 CrawlerError::parsing(&self.path, self.source.clone(), ParseTarget::Array, None)
290 })?;
291 let path_clone = self.path.clone();
292 let cur_back = json_array.len().saturating_sub(1);
293 Ok(JsonCrawlerArrayIterMut {
294 source: self.source.clone(),
295 array: json_array.iter_mut(),
296 path: path_clone,
297 cur_front: 0,
298 cur_back,
299 })
300 }
301 fn navigate_index(self, index: usize) -> CrawlerResult<Self> {
302 let mut path_clone = self.path.clone();
303 path_clone.push(JsonPath::IndexNum(index));
304 let crawler = self
305 .crawler
306 .get_mut(index)
307 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?;
308 Ok(Self {
309 source: self.source,
310 crawler,
311 path: path_clone,
312 })
313 }
314 fn borrow_index(&mut self, index: usize) -> CrawlerResult<Self::BorrowTo<'_>> {
315 let mut path_clone = self.path.clone();
316 path_clone.push(JsonPath::IndexNum(index));
317 let crawler = self
318 .crawler
319 .get_mut(index)
320 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?;
321 Ok(JsonCrawlerBorrowed {
322 source: self.source.clone(),
323 crawler,
324 path: path_clone,
325 })
326 }
327 fn borrow_mut(&mut self) -> Self::BorrowTo<'_> {
328 JsonCrawlerBorrowed {
329 source: self.source.clone(),
330 crawler: self.crawler,
331 path: self.path.to_owned(),
332 }
333 }
334 fn get_path(&self) -> String {
335 (&self.path).into()
336 }
337 fn take_value<T: DeserializeOwned>(&mut self) -> CrawlerResult<T> {
338 serde_json::from_value(self.crawler.take()).map_err(|e| {
339 CrawlerError::parsing(
340 &self.path,
341 self.source.clone(),
342 ParseTarget::Other(std::any::type_name::<T>().to_string()),
343 Some(format!("{e}")),
344 )
345 })
346 }
347 fn take_value_pointers<T: DeserializeOwned, S: AsRef<str>>(
348 &mut self,
349 paths: &[S],
350 ) -> CrawlerResult<T> {
351 let mut path_clone = self.path.clone();
352 let Some((found, path)) = paths
353 .iter()
354 .find_map(|p| self.crawler.pointer_mut(p.as_ref()).map(|v| (v.take(), p)))
355 else {
356 return Err(CrawlerError::paths_not_found(
357 path_clone,
358 self.source.clone(),
359 paths.iter().map(|s| s.as_ref().to_string()).collect(),
360 ));
361 };
362 path_clone.push(JsonPath::Pointer(path.as_ref().to_string()));
363 serde_json::from_value(found).map_err(|e| {
364 CrawlerError::parsing(
365 &path_clone,
366 self.source.clone(),
367 ParseTarget::Other(std::any::type_name::<T>().to_string()),
368 Some(format!("{e}")),
369 )
370 })
371 }
372 fn borrow_value<T: for<'de> Deserialize<'de>>(&self) -> CrawlerResult<T> {
373 T::deserialize(&*self.crawler).map_err(|e| {
374 CrawlerError::parsing(
375 &self.path,
376 self.source.clone(),
377 ParseTarget::Other(std::any::type_name::<T>().to_string()),
378 Some(format!("{e}")),
379 )
380 })
381 }
382 fn borrow_value_pointer<T: for<'de> Deserialize<'de>>(
383 &self,
384 path: impl AsRef<str>,
385 ) -> CrawlerResult<T> {
386 let mut path_clone = self.path.clone();
387 path_clone.push(JsonPath::pointer(path.as_ref()));
388 T::deserialize(
390 self.crawler
391 .pointer(path.as_ref())
392 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?,
393 )
394 .map_err(|e| {
395 CrawlerError::parsing(
396 &path_clone,
397 self.source.clone(),
398 ParseTarget::Other(std::any::type_name::<T>().to_string()),
399 Some(format!("{e}")),
400 )
401 })
402 }
403 fn path_exists(&self, path: &str) -> bool {
404 self.crawler.pointer(path).is_some()
405 }
406 fn get_source(&self) -> Arc<String> {
407 self.source.clone()
408 }
409}
410
411impl JsonCrawler for JsonCrawlerOwned {
412 type BorrowTo<'a>
413 = JsonCrawlerBorrowed<'a>
414 where
415 Self: 'a;
416 type IterMut<'a>
417 = JsonCrawlerArrayIterMut<'a>
418 where
419 Self: 'a;
420 type IntoIter = JsonCrawlerArrayIntoIter;
421 fn try_into_iter(self) -> CrawlerResult<Self::IntoIter> {
422 if let JsonCrawlerOwned {
423 source,
424 crawler: serde_json::Value::Array(array),
425 path,
426 } = self
427 {
428 let cur_back = array.len().saturating_sub(1);
429 return Ok(JsonCrawlerArrayIntoIter {
430 source,
431 array: array.into_iter(),
432 path,
433 cur_front: 0,
434 cur_back,
435 });
436 }
437 Err(CrawlerError::parsing(
438 &self.path,
439 self.source.clone(),
440 ParseTarget::Array,
441 None,
442 ))
443 }
444 fn try_iter_mut(&mut self) -> CrawlerResult<Self::IterMut<'_>> {
445 let json_array = self.crawler.as_array_mut().ok_or_else(|| {
446 CrawlerError::parsing(&self.path, self.source.clone(), ParseTarget::Array, None)
447 })?;
448 let path_clone = self.path.clone();
449 let cur_back = json_array.len().saturating_sub(1);
450 Ok(JsonCrawlerArrayIterMut {
451 source: self.source.clone(),
452 array: json_array.iter_mut(),
453 path: path_clone,
454 cur_front: 0,
455 cur_back,
456 })
457 }
458 fn navigate_pointer(self, new_path: impl AsRef<str>) -> CrawlerResult<Self> {
459 let Self {
460 source,
461 crawler: mut old_crawler,
462 mut path,
463 } = self;
464 path.push(JsonPath::pointer(new_path.as_ref()));
465 let crawler = old_crawler
466 .pointer_mut(new_path.as_ref())
467 .map(|v| v.take())
468 .ok_or_else(|| CrawlerError::navigation(&path, source.clone()))?;
469 Ok(Self {
470 source,
471 crawler,
472 path,
473 })
474 }
475 fn navigate_index(self, index: usize) -> CrawlerResult<Self> {
476 let Self {
477 source,
478 crawler: mut old_crawler,
479 mut path,
480 } = self;
481 path.push(JsonPath::IndexNum(index));
482 let crawler = old_crawler
483 .get_mut(index)
484 .map(|v| v.take())
485 .ok_or_else(|| CrawlerError::navigation(&path, source.clone()))?;
486 Ok(Self {
487 source,
488 crawler,
489 path,
490 })
491 }
492 fn borrow_pointer(&mut self, path: impl AsRef<str>) -> CrawlerResult<Self::BorrowTo<'_>> {
493 let mut path_clone = self.path.clone();
494 path_clone.push(JsonPath::Pointer(path.as_ref().to_owned()));
495 let crawler = self
496 .crawler
497 .pointer_mut(path.as_ref())
498 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?;
499 Ok(JsonCrawlerBorrowed {
500 source: self.source.clone(),
501 crawler,
502 path: path_clone,
503 })
504 }
505 fn borrow_index(&mut self, index: usize) -> CrawlerResult<Self::BorrowTo<'_>> {
506 let mut path_clone = self.path.clone();
507 path_clone.push(JsonPath::IndexNum(index));
508 let crawler = self
509 .crawler
510 .get_mut(index)
511 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?;
512 Ok(JsonCrawlerBorrowed {
513 source: self.source.clone(),
514 crawler,
515 path: path_clone,
516 })
517 }
518 fn borrow_mut(&mut self) -> Self::BorrowTo<'_> {
519 JsonCrawlerBorrowed {
520 source: self.source.clone(),
521 crawler: &mut self.crawler,
522 path: self.path.to_owned(),
523 }
524 }
525 fn take_value<T: DeserializeOwned>(&mut self) -> CrawlerResult<T> {
526 serde_json::from_value(self.crawler.take()).map_err(|e| {
527 CrawlerError::parsing(
528 &self.path,
529 self.source.clone(),
530 ParseTarget::Other(std::any::type_name::<T>().to_string()),
531 Some(format!("{e}")),
532 )
533 })
534 }
535 fn take_value_pointer<T: DeserializeOwned>(
536 &mut self,
537 path: impl AsRef<str>,
538 ) -> CrawlerResult<T> {
539 let mut path_clone = self.path.clone();
540 path_clone.push(JsonPath::pointer(path.as_ref()));
541 serde_json::from_value(
542 self.crawler
543 .pointer_mut(path.as_ref())
544 .map(|v| v.take())
545 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?,
546 )
547 .map_err(|e| {
548 CrawlerError::parsing(
549 &path_clone,
550 self.source.clone(),
551 ParseTarget::Other(std::any::type_name::<T>().to_string()),
552 Some(format!("{e}")),
553 )
554 })
555 }
556 fn take_value_pointers<T: DeserializeOwned, S: AsRef<str>>(
557 &mut self,
558 paths: &[S],
559 ) -> CrawlerResult<T> {
560 let mut path_clone = self.path.clone();
561 let Some((found, path)) = paths
562 .iter()
563 .find_map(|p| self.crawler.pointer_mut(p.as_ref()).map(|v| (v.take(), p)))
564 else {
565 return Err(CrawlerError::paths_not_found(
566 path_clone,
567 self.source.clone(),
568 paths.iter().map(|s| s.as_ref().to_string()).collect(),
569 ));
570 };
571 path_clone.push(JsonPath::Pointer(path.as_ref().to_string()));
572 serde_json::from_value(found).map_err(|e| {
573 CrawlerError::parsing(
574 &path_clone,
575 self.source.clone(),
576 ParseTarget::Other(std::any::type_name::<T>().to_string()),
577 Some(format!("{e}")),
578 )
579 })
580 }
581 fn borrow_value<T: DeserializeOwned>(&self) -> CrawlerResult<T> {
582 T::deserialize(&self.crawler).map_err(|e| {
583 CrawlerError::parsing(
584 &self.path,
585 self.source.clone(),
586 ParseTarget::Other(std::any::type_name::<T>().to_string()),
587 Some(format!("{e}")),
588 )
589 })
590 }
591 fn borrow_value_pointer<T: DeserializeOwned>(&self, path: impl AsRef<str>) -> CrawlerResult<T> {
592 let mut path_clone = self.path.clone();
593 path_clone.push(JsonPath::pointer(path.as_ref()));
594 T::deserialize(
595 self.crawler
596 .pointer(path.as_ref())
597 .ok_or_else(|| CrawlerError::navigation(&path_clone, self.source.clone()))?,
598 )
599 .map_err(|e| {
600 CrawlerError::parsing(
601 &path_clone,
602 self.source.clone(),
603 ParseTarget::Other(std::any::type_name::<T>().to_string()),
604 Some(format!("{e}")),
605 )
606 })
607 }
608 fn path_exists(&self, path: &str) -> bool {
609 self.crawler.pointer(path).is_some()
610 }
611 fn get_source(&self) -> Arc<String> {
612 self.source.clone()
613 }
614 fn get_path(&self) -> String {
615 (&self.path).into()
616 }
617}
618
619#[derive(Clone, PartialEq, Debug)]
620pub enum JsonPath {
621 Pointer(String),
622 IndexNum(usize),
623}
624#[derive(Clone, Default, PartialEq, Debug)]
625struct PathList {
626 list: Vec<JsonPath>,
627}
628
629impl From<&JsonPath> for String {
630 fn from(value: &JsonPath) -> Self {
631 match value {
632 JsonPath::Pointer(p) => p.to_owned(),
633 JsonPath::IndexNum(i) => format! {"/{i}"},
634 }
635 }
636}
637impl JsonPath {
638 pub fn pointer<S: Into<String>>(path: S) -> Self {
639 JsonPath::Pointer(path.into())
640 }
641}
642impl PathList {
643 fn with(mut self, path: JsonPath) -> Self {
644 self.list.push(path);
645 self
646 }
647 fn push(&mut self, path: JsonPath) {
648 self.list.push(path)
649 }
650}
651
652impl From<&PathList> for String {
654 fn from(value: &PathList) -> Self {
655 let mut path = String::new();
656 for p in &value.list {
657 path.push_str(String::from(p).as_str());
658 }
659 path
660 }
661}
662impl From<PathList> for String {
663 fn from(value: PathList) -> Self {
664 let mut path = String::new();
665 for p in &value.list {
666 path.push_str(String::from(p).as_str());
667 }
668 path
669 }
670}