use crate::error::Result;
use crate::record::Record;
pub trait FormatReader: std::fmt::Debug {
fn read_record(&mut self) -> Result<Option<Record>>;
fn read_all(&mut self) -> Result<Vec<Record>> {
let mut records = Vec::new();
while let Some(record) = self.read_record()? {
records.push(record);
}
Ok(records)
}
fn records_read(&self) -> Option<usize> {
None
}
}
pub trait FormatWriter: std::fmt::Debug {
fn write_record(&mut self, record: &Record) -> Result<()>;
fn write_batch(&mut self, records: &[Record]) -> Result<()> {
for record in records {
self.write_record(record)?;
}
Ok(())
}
fn finish(&mut self) -> Result<()>;
fn records_written(&self) -> Option<usize> {
None
}
}
pub trait FormatReaderExt: FormatReader {
fn records(&mut self) -> RecordIterator<'_, Self>
where
Self: Sized,
{
RecordIterator { reader: self }
}
}
impl<T: FormatReader> FormatReaderExt for T {}
#[derive(Debug)]
pub struct RecordIterator<'a, R: FormatReader> {
reader: &'a mut R,
}
impl<R: FormatReader> Iterator for RecordIterator<'_, R> {
type Item = Result<Record>;
fn next(&mut self) -> Option<Self::Item> {
match self.reader.read_record() {
Ok(Some(record)) => Some(Ok(record)),
Ok(None) => None,
Err(e) => Some(Err(e)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Leader;
fn test_leader() -> Leader {
Leader::from_bytes(b"00000nam a2200000 i 4500").unwrap()
}
#[derive(Debug)]
struct MockReader {
records: Vec<Record>,
index: usize,
}
impl MockReader {
fn new(records: Vec<Record>) -> Self {
Self { records, index: 0 }
}
}
impl FormatReader for MockReader {
fn read_record(&mut self) -> Result<Option<Record>> {
if self.index < self.records.len() {
let record = self.records[self.index].clone();
self.index += 1;
Ok(Some(record))
} else {
Ok(None)
}
}
fn records_read(&self) -> Option<usize> {
Some(self.index)
}
}
#[derive(Debug)]
struct MockWriter {
records: Vec<Record>,
finished: bool,
}
impl MockWriter {
fn new() -> Self {
Self {
records: Vec::new(),
finished: false,
}
}
}
impl FormatWriter for MockWriter {
fn write_record(&mut self, record: &Record) -> Result<()> {
if self.finished {
return Err(crate::MarcError::InvalidRecord(
"Writer already finished".to_string(),
));
}
self.records.push(record.clone());
Ok(())
}
fn finish(&mut self) -> Result<()> {
self.finished = true;
Ok(())
}
fn records_written(&self) -> Option<usize> {
Some(self.records.len())
}
}
#[test]
fn test_reader_read_all() {
let records = vec![
Record::new(test_leader()),
Record::new(test_leader()),
Record::new(test_leader()),
];
let mut reader = MockReader::new(records.clone());
let result = reader.read_all().unwrap();
assert_eq!(result.len(), 3);
assert_eq!(reader.records_read(), Some(3));
}
#[test]
fn test_reader_empty() {
let mut reader = MockReader::new(vec![]);
let result = reader.read_all().unwrap();
assert!(result.is_empty());
assert_eq!(reader.records_read(), Some(0));
}
#[test]
fn test_reader_iterator() {
let records = vec![Record::new(test_leader()), Record::new(test_leader())];
let mut reader = MockReader::new(records);
let mut count = 0;
for result in reader.records() {
result.unwrap();
count += 1;
}
assert_eq!(count, 2);
}
#[test]
fn test_writer_batch() {
let records = vec![
Record::new(test_leader()),
Record::new(test_leader()),
Record::new(test_leader()),
];
let mut writer = MockWriter::new();
writer.write_batch(&records).unwrap();
assert_eq!(writer.records_written(), Some(3));
writer.finish().unwrap();
assert!(writer.finished);
}
#[test]
fn test_writer_single_records() {
let mut writer = MockWriter::new();
writer.write_record(&Record::new(test_leader())).unwrap();
writer.write_record(&Record::new(test_leader())).unwrap();
assert_eq!(writer.records_written(), Some(2));
writer.finish().unwrap();
}
#[test]
fn test_writer_cannot_write_after_finish() {
let mut writer = MockWriter::new();
writer.finish().unwrap();
let result = writer.write_record(&Record::new(test_leader()));
assert!(result.is_err());
}
}