Broke out next_inner

This commit is contained in:
Josh Mitchell
2020-11-11 17:11:55 +11:00
parent 6d911fae0b
commit 53dd997129
3 changed files with 48 additions and 31 deletions

View File

@@ -1,8 +1,8 @@
use crate::c_abi; use crate::c_abi;
use crate::FileMode; use crate::FileMode;
use crate::Frame; use crate::Frame;
use std::path::{Path, PathBuf};
use std::error::Error as StdError; use std::error::Error as StdError;
use std::path::{Path, PathBuf};
/// Error type for the xdrfile library /// Error type for the xdrfile library
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@@ -26,7 +26,8 @@ pub enum Error {
InvalidOsStr, InvalidOsStr,
/// A path could not be converted to &CStr because it had a null byte /// A path could not be converted to &CStr because it had a null byte
NullInStr(std::ffi::NulError), NullInStr(std::ffi::NulError),
CouldNotCheckNAtoms(Box<Error>), CheckNAtomsDuringRead(Box<Error>),
CheckNAtomsDuringIter(Box<Error>),
} }
impl Error { impl Error {
@@ -60,9 +61,10 @@ impl Error {
impl std::error::Error for Error { impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use Error::*;
match &self { match &self {
Error::NullInStr(err) => Some(err), NullInStr(err) => Some(err),
Error::CouldNotCheckNAtoms(err) => Some(err.as_ref()), CheckNAtomsDuringRead(err) | CheckNAtomsDuringIter(err) => Some(err.as_ref()),
_ => None, _ => None,
} }
} }
@@ -121,10 +123,14 @@ impl std::fmt::Display for Error {
} }
InvalidOsStr => write!(f, "Paths must be valid unicode on this platform"), InvalidOsStr => write!(f, "Paths must be valid unicode on this platform"),
NullInStr(_err) => write!(f, "Paths cannot include null bytes"), NullInStr(_err) => write!(f, "Paths cannot include null bytes"),
CouldNotCheckNAtoms(_err) => write!( CheckNAtomsDuringRead(_err) => write!(
f, f,
"Failed to check number of atoms in trajectory while reading a frame" "Failed to check number of atoms in trajectory while reading a frame"
), ),
CheckNAtomsDuringIter(_err) => write!(
f,
"Failed to check number of atoms in trajectory while creating iterator"
),
} }
} }
} }
@@ -234,8 +240,8 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::ffi::NulError;
use std::ffi::CString; use std::ffi::CString;
use std::ffi::NulError;
#[test] #[test]
fn test_is_eof() { fn test_is_eof() {
@@ -293,12 +299,18 @@ mod tests {
let path = Path::new("."); let path = Path::new(".");
let mode = FileMode::Read; let mode = FileMode::Read;
let expected = Error::CouldNotOpen{path: path.to_path_buf(), mode: mode.to_owned()}; let expected = Error::CouldNotOpen {
path: path.to_path_buf(),
mode: mode.to_owned(),
};
let err = Error::from((path, mode)); let err = Error::from((path, mode));
assert_eq!(expected, err); assert_eq!(expected, err);
let frame = Frame::with_capacity(0); let frame = Frame::with_capacity(0);
let expected = Error::WrongSizeFrame{expected: 10, found: 0}; let expected = Error::WrongSizeFrame {
expected: 10,
found: 0,
};
let err = Error::from((&frame, 10)); let err = Error::from((&frame, 10));
assert_eq!(expected, err); assert_eq!(expected, err);
} }

View File

@@ -45,24 +45,13 @@ pub struct TrajectoryIterator<T> {
num_atoms: Result<u32>, num_atoms: Result<u32>,
} }
impl<T> Iterator for TrajectoryIterator<T> impl<T: Trajectory> TrajectoryIterator<T> {
where /// Inner function for `next()` to seperate error handling from iteration logic
T: Trajectory, fn next_inner(&mut self) -> <Self as Iterator>::Item {
{
type Item = Result<Rc<Frame>>;
fn next(&mut self) -> Option<Self::Item> {
if self.has_error {
return None;
}
// If we couldn't read the number of frames when we called into_iter, return that error now // If we couldn't read the number of frames when we called into_iter, return that error now
let num_atoms = match &self.num_atoms { let num_atoms = match &self.num_atoms {
&Ok(n) => n, &Ok(n) => n,
Err(e) => { Err(e) => Err(Error::CheckNAtomsDuringIter(Box::new(e.clone())))?,
self.has_error = true;
return Some(Err(e.clone()));
}
}; };
// Reuse old frame // Reuse old frame
@@ -75,8 +64,24 @@ where
} }
}; };
match self.trajectory.read(item) { self.trajectory.read(item)?;
Ok(()) => Some(Ok(Rc::clone(&self.item))), Ok(Rc::clone(&self.item))
}
}
impl<T> Iterator for TrajectoryIterator<T>
where
T: Trajectory,
{
type Item = Result<Rc<Frame>>;
fn next(&mut self) -> Option<Self::Item> {
if self.has_error {
return None;
}
match self.next_inner() {
Ok(item) => Some(Ok(item)),
Err(e) if e.is_eof() => None, Err(e) if e.is_eof() => None,
Err(e) => { Err(e) => {
self.has_error = true; self.has_error = true;

View File

@@ -216,9 +216,9 @@ impl Trajectory for XTCTrajectory {
fn read(&mut self, frame: &mut Frame) -> Result<()> { fn read(&mut self, frame: &mut Frame) -> Result<()> {
let mut step: i32 = 0; let mut step: i32 = 0;
let num_atoms = self let num_atoms =
.get_num_atoms() self.get_num_atoms()
.map_err(|e| Error::CouldNotCheckNAtoms(Box::new(e)))? as usize; .map_err(|e| Error::CheckNAtomsDuringRead(Box::new(e)))? as usize;
if num_atoms != frame.coords.len() { if num_atoms != frame.coords.len() {
Err((&*frame, num_atoms))?; Err((&*frame, num_atoms))?;
} }
@@ -335,9 +335,9 @@ impl Trajectory for TRRTrajectory {
let mut step: i32 = 0; let mut step: i32 = 0;
let mut lambda: f32 = 0.0; let mut lambda: f32 = 0.0;
let num_atoms = self let num_atoms =
.get_num_atoms() self.get_num_atoms()
.map_err(|e| Error::CouldNotCheckNAtoms(Box::new(e)))? as usize; .map_err(|e| Error::CheckNAtomsDuringRead(Box::new(e)))? as usize;
if num_atoms != frame.coords.len() { if num_atoms != frame.coords.len() {
Err((&*frame, num_atoms))?; Err((&*frame, num_atoms))?;
} }