1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
use anyhow::{anyhow, Error}; use regex::Regex; pub struct KeyFinder { keys: Option<(usize, usize, Vec<bool>)>, sep: Regex, } impl KeyFinder { pub fn new(keys: Option<Vec<usize>>, sep: Regex) -> Result<Self, Error> { let keys = keys.map(|mut keys| { keys.sort_unstable(); let last = *keys.last().unwrap(); ( keys.len(), last, (0..=last) .map(|i| keys.contains(&(i + 1))) .collect::<Vec<_>>(), ) }); Ok(KeyFinder { keys, sep }) } pub fn key<'a>(&self, record: &'a str, s: &'a mut String) -> Result<&'a str, Error> { let (num, last, keep) = match &self.keys { None => return Ok(record), Some((num, _, _)) if *num == 0 => return Ok(record), Some((num, last, keep)) => (num, last, keep), }; let mut fields = keep .iter() .zip(self.sep.splitn(record, last + 2)) .filter_map(|(keep, field)| if *keep { Some(field) } else { None }); if *num == 1 { return match fields.next() { Some(f) => Ok(f), None => Err(anyhow!("not enough fields to make key")), }; } let mut found = 0; for f in fields { s.push(' '); s.push_str(f); found += 1; } if found == *num { Ok(s) } else { Err(anyhow!("not enough fields to make key")) } } }