use crate::{errors::ParseTprError, Precision, TprHeader};
use super::xdr::XdrFile;
#[derive(Debug, Clone)]
pub(super) struct Coordinates {
pub(super) positions: Vec<[f64; 3]>,
pub(super) velocities: Vec<[f64; 3]>,
pub(super) forces: Vec<[f64; 3]>,
}
impl Coordinates {
pub(super) fn parse(
xdrfile: &mut XdrFile,
tpr_header: &TprHeader,
) -> Result<Self, ParseTprError> {
let positions = if tpr_header.has_positions {
Self::read_block(xdrfile, tpr_header.precision, tpr_header.n_atoms)?
} else {
Vec::default()
};
let velocities = if tpr_header.has_velocities {
Self::read_block(xdrfile, tpr_header.precision, tpr_header.n_atoms)?
} else {
Vec::default()
};
let forces = if tpr_header.has_forces {
Self::read_block(xdrfile, tpr_header.precision, tpr_header.n_atoms)?
} else {
Vec::default()
};
Ok(Coordinates {
positions,
velocities,
forces,
})
}
fn read_block(
xdrfile: &mut XdrFile,
precision: Precision,
n_items: i32,
) -> Result<Vec<[f64; 3]>, ParseTprError> {
(0..n_items)
.map(|_| xdrfile.read_vector3(precision))
.collect::<Result<Vec<[f64; 3]>, std::io::Error>>()
.map_err(ParseTprError::CouldNotRead)
}
}