Add filter function
This commit is contained in:
75
src/filter.rs
Normal file
75
src/filter.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{Read, Write},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
pub enum Comparator<T: PartialOrd> {
|
||||
EQUAL(T),
|
||||
NOT_EQUAL(T),
|
||||
GREATER_THAN(T),
|
||||
LESS_THAN(T),
|
||||
IN(Vec<T>),
|
||||
NOT_IN(Vec<T>),
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> Comparator<T> {
|
||||
pub fn is_valid(&self, value: T) -> bool {
|
||||
match self {
|
||||
Comparator::EQUAL(v) => value == *v,
|
||||
Comparator::NOT_EQUAL(v) => value != *v,
|
||||
Comparator::GREATER_THAN(v) => value > *v,
|
||||
Comparator::LESS_THAN(v) => value < *v,
|
||||
Comparator::IN(v) => v.contains(&value),
|
||||
Comparator::NOT_IN(v) => !v.contains(&value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FieldName {
|
||||
// Name of the field this validator should work on
|
||||
fn get_field_name(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait DataValidator: FieldName {
|
||||
// Whether the given value is valid for the validator
|
||||
fn is_valid(&self, s: &String) -> bool;
|
||||
}
|
||||
|
||||
pub struct FilterRule<T: PartialOrd> {
|
||||
column_name: String,
|
||||
comparator: Comparator<T>,
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> FieldName for FilterRule<T> {
|
||||
fn get_field_name(&self) -> String {
|
||||
self.column_name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromStr + PartialOrd> DataValidator for FilterRule<T> {
|
||||
fn is_valid(&self, s: &String) -> bool {
|
||||
s.parse().map_or(false, |f| self.comparator.is_valid(f))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all lines from the input file to the output file, skipping records
|
||||
* that don't satisfy the filter criteria
|
||||
*/
|
||||
pub fn filter_file(
|
||||
rules: Vec<&dyn DataValidator>,
|
||||
input: &mut csv::Reader<impl Read>,
|
||||
output: &mut csv::Writer<impl Write>,
|
||||
) -> anyhow::Result<()> {
|
||||
for line in input.deserialize() {
|
||||
let line: HashMap<String, String> = line?;
|
||||
if rules.iter().all(|rule| {
|
||||
line.get(&rule.get_field_name())
|
||||
.map_or(true, |value| rule.is_valid(value))
|
||||
}) {
|
||||
output.serialize(line)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -15,6 +15,8 @@ pub use self::shared_models::*;
|
||||
|
||||
pub mod link;
|
||||
|
||||
pub mod filter;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn move_money_from_text(
|
||||
rules: *const c_char,
|
||||
|
||||
Reference in New Issue
Block a user