use crate::{file_handler::FileHandler, Result};
use anyhow::{anyhow, bail, Context};
use skip_error::SkipError;
use tracing::info;
use typed_index_collection::{CollectionWithId, Id};
pub fn read_objects<H, O>(
file_handler: &mut H,
file_name: &str,
required_file: bool,
) -> Result<Vec<O>>
where
for<'a> &'a mut H: FileHandler,
O: for<'de> serde::Deserialize<'de>,
{
let (reader, path) = file_handler.get_file_if_exists(file_name)?;
let file_name = path.file_name();
let basename = file_name.map_or(path.to_string_lossy(), |b| b.to_string_lossy());
match (reader, required_file) {
(None, false) => {
info!("Skipping {}", basename);
Ok(vec![])
}
(None, true) => {
bail!("file {:?} not found", path)
}
(Some(reader), _) => {
info!("Reading {}", basename);
let mut rdr = csv::ReaderBuilder::new()
.flexible(true)
.trim(csv::Trim::All)
.from_reader(reader);
Ok(rdr
.deserialize()
.collect::<Result<_, _>>()
.with_context(|| format!("Error reading {:?}", path))?)
}
}
}
pub fn read_objects_loose<H, O>(
file_handler: &mut H,
file_name: &str,
required_file: bool,
) -> Result<Vec<O>>
where
for<'a> &'a mut H: FileHandler,
O: for<'de> serde::Deserialize<'de>,
{
let (reader, path) = file_handler.get_file_if_exists(file_name)?;
let file_name = path.file_name();
let basename = file_name.map_or(path.to_string_lossy(), |b| b.to_string_lossy());
match (reader, required_file) {
(None, false) => {
info!("Skipping {}", basename);
Ok(vec![])
}
(None, true) => {
bail!("file {:?} not found", path)
}
(Some(reader), _) => {
info!("Reading {}", basename);
let mut rdr = csv::ReaderBuilder::new()
.flexible(true)
.trim(csv::Trim::All)
.from_reader(reader);
let objects = rdr
.deserialize()
.map(|object| object.with_context(|| format!("Error reading {:?}", path)))
.skip_error_and_warn()
.collect();
Ok(objects)
}
}
}
pub fn read_collection<H, O>(file_handler: &mut H, file_name: &str) -> Result<CollectionWithId<O>>
where
for<'a> &'a mut H: FileHandler,
O: for<'de> serde::Deserialize<'de> + Id<O>,
{
let vec = read_objects(file_handler, file_name, true)?;
CollectionWithId::new(vec).map_err(|e| anyhow!("{}", e))
}
pub fn read_opt_collection<H, O>(
file_handler: &mut H,
file_name: &str,
) -> Result<CollectionWithId<O>>
where
for<'a> &'a mut H: FileHandler,
O: for<'de> serde::Deserialize<'de> + Id<O>,
{
let vec = read_objects(file_handler, file_name, false)?;
CollectionWithId::new(vec).map_err(|e| anyhow!("{}", e))
}