Split readers/writers into separate module

This commit is contained in:
Piv
2023-07-28 20:28:58 +09:30
parent fc633153bb
commit 12add6e5c1
4 changed files with 68 additions and 25 deletions

View File

@@ -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
View 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!()
// }
// }

View File

@@ -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,

View File

@@ -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 {