1 /// Code to parse a dump file
2 use std::collections::HashMap;
3 use std::convert::TryInto;
4 use std::iter::Peekable;
8 pub struct BlockReader<I>
10 I: Iterator<Item = std::io::Result<String>>,
20 impl<I> BlockReader<I>
22 I: Iterator<Item = std::io::Result<String>>,
24 pub fn new(iter: I) -> Self {
26 iter: iter.peekable(),
30 /// Extract the initial header from the file.
31 pub fn extract_header(&mut self) -> String {
32 let mut res: String = "".to_string();
34 while let Some(Ok(line)) = self.iter.peek() {
35 if !line.starts_with('#') {
38 res.push_str(line.as_str());
40 let _ = self.iter.next();
46 /// Extract the next empty-line-delimited block from the file.
48 /// This isn't terribly efficient, but it's "fast enough".
49 fn get_block(&mut self) -> Option<std::io::Result<AnyBlock>> {
50 let mut kv = HashMap::new();
52 while let Some(line) = self.iter.next() {
54 if let Err(e) = line {
57 let line_orig = line.unwrap();
58 let line = line_orig.splitn(2, '#').next().unwrap().trim();
66 let kwds: Vec<_> = line.splitn(2, ':').collect();
68 return None; // XXXX handle the error better.
70 kv.insert(kwds[0].trim().to_string(), kwds[1].trim().to_string());
77 let net = if let Some(net) = kv.get("net") {
78 net.parse().unwrap() //XXXX handle the error better.
80 return Some(Ok(AnyBlock::NotNet));
83 let cc = if let Some(country) = kv.get("country") {
84 assert!(country.as_bytes().len() == 2);
85 country.as_bytes()[0..2].try_into().unwrap()
87 return Some(Ok(AnyBlock::NotNet));
90 fn is_true(v: Option<&String>) -> bool {
92 Some(s) => s == "true",
97 let is_anon_proxy = is_true(kv.get("is-anonymous-proxy"));
98 let is_anycast = is_true(kv.get("is-anycast-proxy"));
99 let is_satellite = is_true(kv.get("is-satellite-provider"));
101 Some(Ok(AnyBlock::NetBlock(NetBlock {
111 impl<I> Iterator for BlockReader<I>
113 I: Iterator<Item = std::io::Result<String>>,
115 type Item = NetBlock;
116 fn next(&mut self) -> Option<Self::Item> {
118 match self.get_block() {
120 Some(Err(_)) => return None,
121 Some(Ok(AnyBlock::NotNet)) => continue,
122 Some(Ok(AnyBlock::NetBlock(n))) => return Some(n),