use super::super::input::{InputBuffer, Limits};
use super::detect::Format;
use crate::diagnostic::Diagnostic;
use crate::diagnostic::{Diagnostics, Strictness};
use crate::structure::Structure;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[non_exhaustive]
pub enum ParseMode {
Strict,
#[default]
Permissive,
Recover,
}
impl ParseMode {
#[must_use]
pub const fn strictness(self) -> Strictness {
match self {
Self::Strict => Strictness::Strict,
Self::Permissive => Strictness::Medium,
Self::Recover => Strictness::Loose,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum MissingElementPolicy {
#[default]
PreserveUnknown,
InferFromAtomName,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum AmbiguousResidueBoundaryPolicy {
#[default]
Reject,
InferFromFileOrder,
}
#[derive(Clone, Debug, Default)]
pub struct ReadOptions {
pub format: Format,
pub mode: ParseMode,
pub only_first_model: bool,
pub only_atomic_coords: bool,
pub discard_hydrogens: bool,
pub missing_element_policy: MissingElementPolicy,
pub ambiguous_residue_boundary_policy: AmbiguousResidueBoundaryPolicy,
pub limits: Limits,
}
impl ReadOptions {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub const fn format(mut self, format: Format) -> Self {
self.format = format;
self
}
#[must_use]
pub const fn mode(mut self, mode: ParseMode) -> Self {
self.mode = mode;
self
}
#[must_use]
pub const fn only_first_model(mut self, only: bool) -> Self {
self.only_first_model = only;
self
}
#[must_use]
pub const fn only_atomic_coords(mut self, only: bool) -> Self {
self.only_atomic_coords = only;
self
}
#[must_use]
pub const fn missing_element_policy(mut self, policy: MissingElementPolicy) -> Self {
self.missing_element_policy = policy;
self
}
#[must_use]
pub const fn ambiguous_residue_boundary_policy(
mut self,
policy: AmbiguousResidueBoundaryPolicy,
) -> Self {
self.ambiguous_residue_boundary_policy = policy;
self
}
#[must_use]
pub const fn discard_hydrogens(mut self, discard: bool) -> Self {
self.discard_hydrogens = discard;
self
}
#[must_use]
pub const fn limits(mut self, limits: Limits) -> Self {
self.limits = limits;
self
}
pub fn finish(
&self,
structure: Structure,
findings: impl IntoIterator<Item = Diagnostic>,
) -> ReadResult {
let mut ordered = Diagnostics::new();
ordered.extend(findings);
let is_error = ordered.has_error(self.mode.strictness());
let findings = ordered.finish();
if is_error {
Err(findings)
} else {
Ok((structure, findings))
}
}
}
pub type ReadResult = Result<(Structure, Vec<Diagnostic>), Vec<Diagnostic>>;
pub trait Reader {
const FORMAT: Format;
fn read(input: &InputBuffer, options: &ReadOptions) -> ReadResult;
}
pub trait Select {
fn accept_model(&self, _model: crate::index::ModelIndex) -> bool {
true
}
fn accept_chain(&self, _chain: crate::index::ChainIndex) -> bool {
true
}
fn accept_residue(&self, _residue: crate::index::ResidueIndex) -> bool {
true
}
fn accept_atom(&self, _atom: crate::index::AtomIndex) -> bool {
true
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct SelectAll;
impl Select for SelectAll {}