Split readers/writers into separate module
This commit is contained in:
@@ -4,6 +4,8 @@ use std::{
|
|||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::io::RecordSerializer;
|
||||||
|
|
||||||
pub enum Comparator<T: PartialOrd> {
|
pub enum Comparator<T: PartialOrd> {
|
||||||
EQUAL(T),
|
EQUAL(T),
|
||||||
NOT_EQUAL(T),
|
NOT_EQUAL(T),
|
||||||
@@ -59,14 +61,20 @@ impl<T: FromStr + PartialOrd> DataValidator for FilterRule<T> {
|
|||||||
*/
|
*/
|
||||||
pub fn filter_file(
|
pub fn filter_file(
|
||||||
rules: Vec<&dyn DataValidator>,
|
rules: Vec<&dyn DataValidator>,
|
||||||
|
// TODO: Custom serialisers/deserialisers so we don't rely on csv only
|
||||||
input: &mut csv::Reader<impl Read>,
|
input: &mut csv::Reader<impl Read>,
|
||||||
output: &mut csv::Writer<impl Write>,
|
output: &mut impl RecordSerializer,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for line in input.deserialize() {
|
for line in input.deserialize() {
|
||||||
let line: HashMap<String, String> = line?;
|
let line: HashMap<String, String> = line?;
|
||||||
if rules.iter().all(|rule| {
|
if rules.iter().all(|rule| {
|
||||||
line.get(&rule.get_field_name())
|
line.get(&rule.get_field_name()).map_or(true, |value| {
|
||||||
.map_or(true, |value| rule.is_valid(value))
|
if value.trim().is_empty() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
rule.is_valid(value)
|
||||||
|
}
|
||||||
|
})
|
||||||
}) {
|
}) {
|
||||||
output.serialize(line)?;
|
output.serialize(line)?;
|
||||||
}
|
}
|
||||||
|
|||||||
53
src/io.rs
Normal file
53
src/io.rs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
io::{Read, Write},
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
|
use csv::DeserializeRecordsIter;
|
||||||
|
use rmp_serde::{Deserializer, Serializer};
|
||||||
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
|
||||||
|
pub trait RecordSerializer {
|
||||||
|
fn serialize(&mut self, record: impl Serialize) -> anyhow::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> RecordSerializer for csv::Writer<W> {
|
||||||
|
fn serialize(&mut self, record: impl Serialize) -> anyhow::Result<()> {
|
||||||
|
self.serialize(record)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> RecordSerializer for Serializer<W> {
|
||||||
|
fn serialize(&mut self, record: impl Serialize) -> anyhow::Result<()> {
|
||||||
|
record.serialize(self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Want to be able to deserialise with serde over a reader like we currently do with the writer
|
||||||
|
// pub trait RecordDeserializer<D: DeserializeOwned, I: Iterator<Item = Result<D, anyhow::Error>>> {
|
||||||
|
// fn deserialize<I>(&mut self) -> I;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<R: Read, D: DeserializeOwned, I: Iterator<Item = Result<D, anyhow::Error>>>
|
||||||
|
// RecordDeserializer<D, I> for csv::Reader<R>
|
||||||
|
// {
|
||||||
|
// fn deserialize(&mut self) -> I {
|
||||||
|
// self.deserialize().into_iter().map(|r| match r {
|
||||||
|
// Ok(ok) => Ok(ok),
|
||||||
|
// Err(err) => bail!(err),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<R: Read> RecordDeserializer for Deserializer<R> {
|
||||||
|
// fn deserialize<I, D>(&mut self) -> I
|
||||||
|
// where
|
||||||
|
// D: DeserializeOwned,
|
||||||
|
// I: Iterator<Item = D>,
|
||||||
|
// {
|
||||||
|
// todo!()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -17,6 +17,8 @@ pub mod link;
|
|||||||
|
|
||||||
pub mod filter;
|
pub mod filter;
|
||||||
|
|
||||||
|
mod io;
|
||||||
|
|
||||||
#[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,
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
io::{Read, Write},
|
io::Read,
|
||||||
};
|
};
|
||||||
|
|
||||||
use csv::Writer;
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nalgebra::{DMatrix, Dynamic, LU};
|
use nalgebra::{DMatrix, Dynamic, LU};
|
||||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use rmp_serde::Serializer;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{CsvAccount, CsvCost};
|
use crate::{io::RecordSerializer, CsvAccount, CsvCost};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum DepartmentType {
|
pub enum DepartmentType {
|
||||||
@@ -769,24 +767,6 @@ fn solve_reciprocal_with_from<T: ReciprocalAllocationSolver + Sync + Send>(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RecordSerializer {
|
|
||||||
fn serialize(&mut self, record: impl Serialize) -> anyhow::Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: Write> RecordSerializer for csv::Writer<W> {
|
|
||||||
fn serialize(&mut self, record: impl Serialize) -> anyhow::Result<()> {
|
|
||||||
self.serialize(record)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: Write> RecordSerializer for Serializer<W> {
|
|
||||||
fn serialize(&mut self, record: impl Serialize) -> anyhow::Result<()> {
|
|
||||||
record.serialize(self)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user