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 link;
|
||||||
|
|
||||||
|
pub mod filter;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn move_money_from_text(
|
pub extern "C" fn move_money_from_text(
|
||||||
rules: *const c_char,
|
rules: *const c_char,
|
||||||
|
|||||||
Reference in New Issue
Block a user