1 /// Code to parse a dump file
2 use std::collections::HashMap;
3 use std::convert::TryInto;
4 use std::iter::Peekable;
6 use super::{AsBlock, NetBlock};
8 pub struct BlockReader<I>
10 I: Iterator<Item = std::io::Result<String>>,
21 impl<I> BlockReader<I>
23 I: Iterator<Item = std::io::Result<String>>,
25 pub fn new(iter: I) -> Self {
27 iter: iter.peekable(),
31 /// Extract the initial header from the file.
32 pub fn extract_header(&mut self) -> String {
33 let mut res: String = "".to_string();
35 while let Some(Ok(line)) = self.iter.peek() {
36 if !line.starts_with('#') {
39 res.push_str(line.as_str());
41 let _ = self.iter.next();
47 /// Extract the next empty-line-delimited block from the file.
49 /// This isn't terribly efficient, but it's "fast enough".
50 fn get_block(&mut self) -> Option<std::io::Result<AnyBlock>> {
51 let mut kv = HashMap::new();
53 for line in self.iter.by_ref() {
55 if let Err(e) = line {
58 let line_orig = line.unwrap();
59 let line = line_orig.split('#').next().unwrap().trim();
67 let kwds: Vec<_> = line.splitn(2, ':').collect();
69 return None; // XXXX handle the error better.
71 kv.insert(kwds[0].trim().to_string(), kwds[1].trim().to_string());
78 if let Some(name) = kv.remove("name") {
79 // This is an AS block.
80 let asn = kv.get("aut-num").unwrap(); // XXXX handle error better
81 assert!(asn.starts_with("AS"));
82 let asn = asn[2..].parse().unwrap();
83 return Some(Ok(AnyBlock::As(AsBlock { name, asn })));
86 let net = if let Some(net) = kv.get("net") {
87 net.parse().unwrap() //XXXX handle the error better.
89 return Some(Ok(AnyBlock::Other));
92 let asn = if let Some(asn) = kv.get("aut-num") {
98 let cc = if let Some(country) = kv.get("country") {
99 assert!(country.as_bytes().len() == 2);
100 country.as_bytes()[0..2].try_into().unwrap()
105 fn is_true(v: Option<&String>) -> bool {
107 Some(s) => s == "true",
112 let is_anon_proxy = is_true(kv.get("is-anonymous-proxy"));
113 let is_anycast = is_true(kv.get("is-anycast-proxy"));
114 let is_satellite = is_true(kv.get("is-satellite-provider"));
116 Some(Ok(AnyBlock::Net(NetBlock {
127 impl<I> Iterator for BlockReader<I>
129 I: Iterator<Item = std::io::Result<String>>,
131 type Item = AnyBlock;
132 fn next(&mut self) -> Option<Self::Item> {
133 match self.get_block() {
134 Some(Ok(b)) => Some(b),