1use crate::{
4 CrawlerError, CrawlerResult, JsonCrawler, JsonCrawlerBorrowed, JsonCrawlerOwned, JsonPath,
5 PathList,
6};
7use std::slice::IterMut;
8use std::sync::Arc;
9use std::vec::IntoIter;
10
11pub trait JsonCrawlerIterator: Iterator
14where
15 Self::Item: JsonCrawler,
16{
17 fn find_path(self, path: impl AsRef<str>) -> CrawlerResult<Self::Item>;
19 fn try_last(self) -> CrawlerResult<Self::Item>;
21}
22
23pub struct JsonCrawlerArrayIterMut<'a> {
24 pub(crate) source: Arc<String>,
25 pub(crate) array: IterMut<'a, serde_json::Value>,
26 pub(crate) path: PathList,
27 pub(crate) cur_front: usize,
28 pub(crate) cur_back: usize,
29}
30
31#[derive(Clone)]
32pub struct JsonCrawlerArrayIntoIter {
33 pub(crate) source: Arc<String>,
34 pub(crate) array: IntoIter<serde_json::Value>,
35 pub(crate) path: PathList,
36 pub(crate) cur_front: usize,
37 pub(crate) cur_back: usize,
38}
39
40impl<'a> Iterator for JsonCrawlerArrayIterMut<'a> {
41 type Item = JsonCrawlerBorrowed<'a>;
42 fn next(&mut self) -> Option<Self::Item> {
43 let crawler = self.array.next()?;
44 let out = Some(JsonCrawlerBorrowed {
45 source: self.source.clone(),
47 crawler,
48 path: self.path.clone().with(JsonPath::IndexNum(self.cur_front)),
51 });
52 self.cur_front += 1;
53 out
54 }
55 fn size_hint(&self) -> (usize, Option<usize>) {
57 (self.array.len(), Some(self.array.len()))
58 }
59}
60
61impl ExactSizeIterator for JsonCrawlerArrayIterMut<'_> {}
63
64impl DoubleEndedIterator for JsonCrawlerArrayIterMut<'_> {
65 fn next_back(&mut self) -> Option<Self::Item> {
66 let crawler = self.array.next_back()?;
67 let out = Some(JsonCrawlerBorrowed {
68 source: self.source.clone(),
70 crawler,
71 path: self.path.clone().with(JsonPath::IndexNum(self.cur_back)),
74 });
75 self.cur_back = self.cur_back.saturating_sub(1);
76 out
77 }
78}
79
80impl JsonCrawlerIterator for JsonCrawlerArrayIterMut<'_> {
81 fn find_path(mut self, path: impl AsRef<str>) -> CrawlerResult<Self::Item> {
82 self.find_map(|crawler| crawler.navigate_pointer(path.as_ref()).ok())
83 .ok_or_else(|| {
84 CrawlerError::path_not_found_in_array(self.path, self.source, path.as_ref())
85 })
86 }
87 fn try_last(self) -> CrawlerResult<Self::Item> {
88 let Self {
89 source,
90 mut array,
91 mut path,
92 ..
93 } = self;
94 let len = array.len();
95 path.push(JsonPath::IndexNum(len - 1));
96 let Some(last_item) = array.next_back() else {
97 return Err(CrawlerError::array_size(path, source, 0));
98 };
99 Ok(Self::Item {
100 source,
101 crawler: last_item,
102 path,
103 })
104 }
105}
106
107impl Iterator for JsonCrawlerArrayIntoIter {
108 type Item = JsonCrawlerOwned;
109 fn next(&mut self) -> Option<Self::Item> {
110 let crawler = self.array.next()?;
111 let out = Some(JsonCrawlerOwned {
112 source: self.source.clone(),
114 crawler,
115 path: self.path.clone().with(JsonPath::IndexNum(self.cur_front)),
118 });
119 self.cur_front += 1;
120 out
121 }
122 fn size_hint(&self) -> (usize, Option<usize>) {
124 (self.array.len(), Some(self.array.len()))
125 }
126}
127impl ExactSizeIterator for JsonCrawlerArrayIntoIter {}
129
130impl DoubleEndedIterator for JsonCrawlerArrayIntoIter {
131 fn next_back(&mut self) -> Option<Self::Item> {
132 let crawler = self.array.next_back()?;
133 let out = Some(JsonCrawlerOwned {
134 source: self.source.clone(),
136 crawler,
137 path: self.path.clone().with(JsonPath::IndexNum(self.cur_back)),
140 });
141 self.cur_back = self.cur_back.saturating_sub(1);
142 out
143 }
144}
145impl JsonCrawlerIterator for JsonCrawlerArrayIntoIter {
146 fn find_path(mut self, path: impl AsRef<str>) -> CrawlerResult<Self::Item> {
147 self.find_map(|crawler| crawler.navigate_pointer(path.as_ref()).ok())
148 .ok_or_else(|| {
149 CrawlerError::path_not_found_in_array(self.path, self.source, path.as_ref())
150 })
151 }
152 fn try_last(self) -> CrawlerResult<Self::Item> {
153 let Self {
154 source,
155 mut array,
156 mut path,
157 ..
158 } = self;
159 let len = array.len();
160 path.push(JsonPath::IndexNum(len - 1));
161 let Some(last_item) = array.next_back() else {
162 return Err(CrawlerError::array_size(path, source, 0));
163 };
164 Ok(Self::Item {
165 source,
166 crawler: last_item,
167 path,
168 })
169 }
170}