bgpkit_parser/parser/iters/
fallible.rs1use crate::error::{ParserError, ParserErrorWithBytes};
9use crate::models::*;
10use crate::parser::BgpkitParser;
11use crate::{Elementor, Filterable};
12use std::io::Read;
13
14pub struct FallibleRecordIterator<R> {
19 parser: BgpkitParser<R>,
20 elementor: Elementor,
21}
22
23impl<R> FallibleRecordIterator<R> {
24 pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
25 FallibleRecordIterator {
26 parser,
27 elementor: Elementor::new(),
28 }
29 }
30}
31
32impl<R: Read> Iterator for FallibleRecordIterator<R> {
33 type Item = Result<MrtRecord, ParserErrorWithBytes>;
34
35 fn next(&mut self) -> Option<Self::Item> {
36 if self.parser.text_dump_iter.is_some() {
39 return None;
40 }
41 loop {
42 match self.parser.next_record() {
43 Ok(record) => {
44 let filters = &self.parser.filters;
46 if filters.is_empty() {
47 return Some(Ok(record));
48 }
49
50 if let MrtMessage::TableDumpV2Message(TableDumpV2Message::PeerIndexTable(_)) =
52 &record.message
53 {
54 let _ = self.elementor.record_to_elems(record.clone());
55 return Some(Ok(record));
56 }
57
58 let elems = self.elementor.record_to_elems(record.clone());
60 if elems.iter().any(|e| e.match_filters(filters)) {
61 return Some(Ok(record));
62 }
63 continue;
65 }
66 Err(e) if matches!(e.error, ParserError::EofExpected) => {
67 return None;
69 }
70 Err(e) => {
71 return Some(Err(e));
73 }
74 }
75 }
76 }
77}
78
79pub struct FallibleElemIterator<R> {
84 cache_elems: Vec<BgpElem>,
85 record_iter: FallibleRecordIterator<R>,
86 elementor: Elementor,
87}
88
89impl<R> FallibleElemIterator<R> {
90 pub(crate) fn new(parser: BgpkitParser<R>) -> Self {
91 FallibleElemIterator {
92 record_iter: FallibleRecordIterator::new(parser),
93 cache_elems: vec![],
94 elementor: Elementor::new(),
95 }
96 }
97}
98
99impl<R: Read> Iterator for FallibleElemIterator<R> {
100 type Item = Result<BgpElem, ParserErrorWithBytes>;
101
102 fn next(&mut self) -> Option<Self::Item> {
103 loop {
104 if let Some(iter) = &mut self.record_iter.parser.text_dump_iter {
106 for elem in iter.by_ref() {
107 if elem.match_filters(&self.record_iter.parser.filters) {
108 return Some(Ok(elem));
109 }
110 }
111 return None;
112 }
113
114 if !self.cache_elems.is_empty() {
116 if let Some(elem) = self.cache_elems.pop() {
117 if elem.match_filters(&self.record_iter.parser.filters) {
118 return Some(Ok(elem));
119 }
120 continue;
122 }
123 }
124
125 match self.record_iter.next() {
127 None => return None,
128 Some(Err(e)) => return Some(Err(e)),
129 Some(Ok(record)) => {
130 let mut elems = self.elementor.record_to_elems(record);
131 if elems.is_empty() {
132 continue;
134 }
135 elems.reverse();
137 self.cache_elems = elems;
138 continue;
139 }
140 }
141 }
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use std::io::Cursor;
149
150 fn create_test_parser_with_errors() -> BgpkitParser<Cursor<Vec<u8>>> {
152 let invalid_data = vec![
154 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, ];
161
162 let cursor = Cursor::new(invalid_data);
163 BgpkitParser::from_reader(cursor)
164 }
165
166 fn create_test_parser_with_valid_data() -> BgpkitParser<Cursor<Vec<u8>>> {
168 let cursor = Cursor::new(vec![]);
171 BgpkitParser::from_reader(cursor)
172 }
173
174 #[test]
175 fn test_fallible_record_iterator_with_errors() {
176 let parser = create_test_parser_with_errors();
177 let mut iter = parser.into_fallible_record_iter();
178
179 let result = iter.next();
181 assert!(result.is_some());
182 assert!(result.unwrap().is_err());
183 }
184
185 #[test]
186 fn test_fallible_record_iterator_eof() {
187 let parser = create_test_parser_with_valid_data();
188 let mut iter = parser.into_fallible_record_iter();
189
190 let result = iter.next();
192 assert!(result.is_none());
193 }
194
195 #[test]
196 fn test_fallible_elem_iterator_with_errors() {
197 let parser = create_test_parser_with_errors();
198 let mut iter = parser.into_fallible_elem_iter();
199
200 let result = iter.next();
202 assert!(result.is_some());
203 assert!(result.unwrap().is_err());
204 }
205
206 #[test]
207 fn test_fallible_elem_iterator_eof() {
208 let parser = create_test_parser_with_valid_data();
209 let mut iter = parser.into_fallible_elem_iter();
210
211 let result = iter.next();
213 assert!(result.is_none());
214 }
215}