use std::{
fs::File,
io::{BufReader, Read},
path::Path,
};
use serde::de::DeserializeOwned;
use crate::{Error, backend, types::DataFormat};
pub fn read_record_from_reader<T: DeserializeOwned>(
reader: impl Read,
data_format: DataFormat,
) -> Result<T, Error> {
match data_format {
DataFormat::Auto => Err(Error::AutoNotSupported),
DataFormat::Json => backend::json::read(reader),
#[cfg(feature = "yaml")]
DataFormat::Yaml => backend::yaml::read(reader),
#[cfg(feature = "messagepack")]
DataFormat::MessagePack => backend::messagepack::read(reader),
#[cfg(feature = "toml")]
DataFormat::Toml => backend::toml::read(reader),
_ => Err(Error::UnsupportedFormat(data_format)),
}
}
pub fn read_records_from_reader<T: DeserializeOwned>(
reader: impl Read,
data_format: DataFormat,
) -> Result<Vec<T>, Error> {
match data_format {
DataFormat::Auto => Err(Error::AutoNotSupported),
DataFormat::Json => backend::json::read(reader),
DataFormat::JsonLines => backend::jsonlines::read(reader),
#[cfg(feature = "csv")]
DataFormat::Csv => backend::csv::read(reader),
#[cfg(feature = "yaml")]
DataFormat::Yaml => backend::yaml::read(reader),
#[cfg(feature = "messagepack")]
DataFormat::MessagePack => backend::messagepack::read(reader),
#[allow(unreachable_patterns)]
_ => Err(Error::UnsupportedFormat(data_format)),
}
}
pub fn read_record_from_file<T: DeserializeOwned>(
path: impl AsRef<Path>,
data_format: DataFormat,
) -> Result<T, Error> {
let path = path.as_ref();
let final_format = if data_format == DataFormat::Auto {
DataFormat::try_from(path)?
} else {
data_format
};
let file = File::open(path)?;
let rdr = BufReader::new(file);
read_record_from_reader(rdr, final_format)
}
pub fn read_records_from_file<T: DeserializeOwned>(
path: impl AsRef<Path>,
data_format: DataFormat,
) -> Result<Vec<T>, Error> {
let path = path.as_ref();
let final_format = if data_format == DataFormat::Auto {
DataFormat::try_from(path)?
} else {
data_format
};
let file = File::open(path)?;
let rdr = BufReader::new(file);
read_records_from_reader(rdr, final_format)
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use serde::Deserialize;
use super::*;
#[allow(dead_code)]
#[derive(Deserialize)]
struct TestRecord {
name: String,
value: i32,
}
#[test]
fn test_read_record_from_reader_auto_not_supported() {
let json_data = r#"{"name": "test", "value": 42}"#;
let reader = Cursor::new(json_data);
let result: Result<TestRecord, Error> = read_record_from_reader(reader, DataFormat::Auto);
assert!(matches!(result, Err(Error::AutoNotSupported)));
}
#[test]
fn test_read_records_from_reader_auto_not_supported() {
let json_data = r#"[{"name": "test1", "value": 1}, {"name": "test2", "value": 2}]"#;
let reader = Cursor::new(json_data);
let result: Result<Vec<TestRecord>, Error> =
read_records_from_reader(reader, DataFormat::Auto);
assert!(matches!(result, Err(Error::AutoNotSupported)));
}
}