use super::ensemble::{CommonRecords, read_ragged};
use super::lines::{Line, Lines};
use super::numbers::decode_window;
use super::state::ReadState;
use molframe_core::diagnostic::{Code, Diagnostic};
use molframe_core::execution::ExecutionContext;
use molframe_core::io::{Format, InputBuffer, ReadOptions, ReadResult, Reader};
#[derive(Clone, Copy, Debug, Default)]
pub struct PdbReader;
impl Reader for PdbReader {
const FORMAT: Format = Format::Pdb;
fn read(input: &InputBuffer, options: &ReadOptions) -> ReadResult {
read_as(input, options, Format::Pdb)
}
}
pub fn read(input: &InputBuffer, options: &ReadOptions) -> ReadResult {
read_as(input, options, Format::Pdb)
}
pub fn read_pqr(input: &InputBuffer, options: &ReadOptions) -> ReadResult {
read_as(input, options, Format::Pqr)
}
pub fn read_pdbqt(input: &InputBuffer, options: &ReadOptions) -> ReadResult {
read_as(input, options, Format::Pdbqt)
}
const WINDOW_LINES: usize = 1 << 15;
fn read_as(input: &InputBuffer, options: &ReadOptions, variant: Format) -> ReadResult {
let Ok(text) = str::from_utf8(input.as_bytes()) else {
return Err(vec![
Diagnostic::new(Code::E1201).with_message("input is not valid text"),
]);
};
let mut common = CommonRecords::new();
let mut state = ReadState::new(options, variant);
let context = ExecutionContext::default();
let mut lines = Lines::new(text);
let mut window = Vec::with_capacity(WINDOW_LINES);
loop {
window.clear();
let mut failure = None;
for line in lines.by_ref().take(WINDOW_LINES) {
match line {
Ok(line) => window.push(line),
Err(finding) => {
failure = Some(finding);
break;
}
}
}
let decoded = decode_window(&window, &context);
for (index, line) in window.iter().enumerate() {
common.observe(line);
let line = Line {
numbers: decoded.get(index).and_then(Option::as_ref),
..*line
};
state.line(&line);
}
if let Some(finding) = failure {
return Err(vec![finding]);
}
if window.len() < WINDOW_LINES {
break;
}
}
if state.requires_ragged() {
drop(state);
return read_ragged(text, options, variant, &common);
}
state.finish()
}
#[cfg(test)]
#[path = "entry_tests.rs"]
mod tests;