bgpkit_parser/parser/
mod.rs1use std::io::Read;
5
6#[macro_use]
7pub mod utils;
8pub mod bgp;
9pub mod bmp;
10pub mod filter;
11pub mod iters;
12pub mod mrt;
13
14#[cfg(feature = "rislive")]
15pub mod rislive;
16
17pub(crate) use self::utils::*;
18
19use crate::models::MrtRecord;
20pub use mrt::mrt_elem::Elementor;
21#[cfg(feature = "oneio")]
22use oneio::{get_cache_reader, get_reader};
23
24pub use crate::error::{ParserError, ParserErrorWithBytes};
25pub use bmp::{parse_bmp_msg, parse_openbmp_header, parse_openbmp_msg};
26pub use filter::*;
27pub use iters::*;
28pub use mrt::*;
29
30#[cfg(feature = "rislive")]
31pub use rislive::parse_ris_live_message;
32
33pub struct BgpkitParser<R> {
34 reader: R,
35 core_dump: bool,
36 filters: Vec<Filter>,
37 options: ParserOptions,
38}
39
40pub(crate) struct ParserOptions {
41 show_warnings: bool,
42}
43impl Default for ParserOptions {
44 fn default() -> Self {
45 ParserOptions {
46 show_warnings: true,
47 }
48 }
49}
50
51#[cfg(feature = "oneio")]
52impl BgpkitParser<Box<dyn Read + Send>> {
53 pub fn new(path: &str) -> Result<Self, ParserErrorWithBytes> {
55 let reader = get_reader(path)?;
56 Ok(BgpkitParser {
57 reader,
58 core_dump: false,
59 filters: vec![],
60 options: ParserOptions::default(),
61 })
62 }
63
64 pub fn new_cached(path: &str, cache_dir: &str) -> Result<Self, ParserErrorWithBytes> {
70 let file_name = path.rsplit('/').next().unwrap().to_string();
71 let new_file_name = format!(
72 "cache-{}",
73 add_suffix_to_filename(file_name.as_str(), crc32(path).as_str())
74 );
75 let reader = get_cache_reader(path, cache_dir, Some(new_file_name), false)?;
76 Ok(BgpkitParser {
77 reader,
78 core_dump: false,
79 filters: vec![],
80 options: ParserOptions::default(),
81 })
82 }
83}
84
85#[cfg(feature = "oneio")]
86fn add_suffix_to_filename(filename: &str, suffix: &str) -> String {
87 let mut parts: Vec<&str> = filename.split('.').collect(); if parts.len() > 1 {
89 let last_part = parts.pop().unwrap(); let new_last_part = format!("{}.{}", suffix, last_part); parts.push(&new_last_part); parts.join(".") } else {
94 format!("{}.{}", filename, suffix)
96 }
97}
98
99impl<R: Read> BgpkitParser<R> {
100 pub fn from_reader(reader: R) -> Self {
102 BgpkitParser {
103 reader,
104 core_dump: false,
105 filters: vec![],
106 options: ParserOptions::default(),
107 }
108 }
109
110 pub fn next_record(&mut self) -> Result<MrtRecord, ParserErrorWithBytes> {
112 parse_mrt_record(&mut self.reader)
113 }
114}
115
116impl<R> BgpkitParser<R> {
117 pub fn enable_core_dump(self) -> Self {
118 BgpkitParser {
119 reader: self.reader,
120 core_dump: true,
121 filters: self.filters,
122 options: self.options,
123 }
124 }
125
126 pub fn disable_warnings(self) -> Self {
127 let mut options = self.options;
128 options.show_warnings = false;
129 BgpkitParser {
130 reader: self.reader,
131 core_dump: self.core_dump,
132 filters: self.filters,
133 options,
134 }
135 }
136
137 pub fn add_filter(
138 self,
139 filter_type: &str,
140 filter_value: &str,
141 ) -> Result<Self, ParserErrorWithBytes> {
142 let mut filters = self.filters;
143 filters.push(Filter::new(filter_type, filter_value)?);
144 Ok(BgpkitParser {
145 reader: self.reader,
146 core_dump: self.core_dump,
147 filters,
148 options: self.options,
149 })
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn test_new_with_reader() {
159 let reader = oneio::get_reader("http://archive.routeviews.org/route-views.ny/bgpdata/2023.02/UPDATES/updates.20230215.0630.bz2").unwrap();
161 assert_eq!(
162 12683,
163 BgpkitParser::from_reader(reader).into_elem_iter().count()
164 );
165
166 let reader = oneio::get_reader("https://spaces.bgpkit.org/parser/update-example").unwrap();
168 assert_eq!(
169 8160,
170 BgpkitParser::from_reader(reader).into_elem_iter().count()
171 );
172 }
173
174 #[test]
175 fn test_new_cached_with_reader() {
176 let url = "https://spaces.bgpkit.org/parser/update-example.gz";
177 let parser = BgpkitParser::new_cached(url, "/tmp/bgpkit-parser-tests")
178 .unwrap()
179 .enable_core_dump()
180 .disable_warnings();
181 let count = parser.into_elem_iter().count();
182 assert_eq!(8160, count);
183 let parser = BgpkitParser::new_cached(url, "/tmp/bgpkit-parser-tests").unwrap();
184 let count = parser.into_elem_iter().count();
185 assert_eq!(8160, count);
186 }
187}