use std::io::{self, prelude::*};
use crate::types::*;
use log::debug;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum CIFParseError {
#[error("error at line {0}: {1}")]
AtLine(usize, Box<CIFRecordParseError>),
#[error("failed to read CIF file")]
Read(#[from] io::Error),
}
pub fn parse_cif<R: Read>(mut content_reader: R) -> Result<crate::types::CIFFile, CIFParseError> {
debug!("Parsing CIF data...");
let mut file = CIFFile::new();
let mut buf = [0u8; 81];
let mut line = 1;
loop {
if line % 10000 == 0 {
log::debug!("Parsed {line} CIF records...");
}
content_reader.read_exact(&mut buf)?;
let record_raw = String::from_utf8_lossy(&buf[0..80]);
let record: CIFRecord = record_raw
.parse()
.map_err(|e| CIFParseError::AtLine(line, Box::new(e)))?;
file.records_mut().push(record.clone());
if let CIFRecord::Trailer = record {
break;
}
line += 1;
}
log::debug!("Parsed {line} records.");
Ok(file)
}