Replace failure library with new Error type

This commit is contained in:
Josh Mitchell
2020-11-07 20:12:41 +11:00
parent 0a613c2022
commit cbd45f74dc
3 changed files with 104 additions and 89 deletions

View File

@@ -8,7 +8,6 @@ description = "Wrapper around the gromacs libxdrfile library. Can be used to rea
build = "build.rs" build = "build.rs"
[dependencies] [dependencies]
failure = "0.1"
lazy-init = "0.3" lazy-init = "0.3"
[dev-dependencies] [dev-dependencies]

View File

@@ -1,10 +1,9 @@
use crate::c_abi::xdrfile::exdrENDOFFILE; use crate::c_abi::xdrfile::exdrENDOFFILE;
use crate::*; use crate::*;
use failure::Error;
use std::rc::Rc; use std::rc::Rc;
impl IntoIterator for XTCTrajectory { impl IntoIterator for XTCTrajectory {
type Item = Result<Rc<Frame>, Error>; type Item = Result<Rc<Frame>>;
type IntoIter = XTCTrajectoryIterator; type IntoIter = XTCTrajectoryIterator;
fn into_iter(mut self) -> Self::IntoIter { fn into_iter(mut self) -> Self::IntoIter {
@@ -30,7 +29,7 @@ pub struct XTCTrajectoryIterator {
} }
impl Iterator for XTCTrajectoryIterator { impl Iterator for XTCTrajectoryIterator {
type Item = Result<Rc<Frame>, Error>; type Item = Result<Rc<Frame>>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
// Reuse old frame // Reuse old frame
@@ -61,7 +60,7 @@ impl Iterator for XTCTrajectoryIterator {
} }
impl IntoIterator for TRRTrajectory { impl IntoIterator for TRRTrajectory {
type Item = Result<Rc<Frame>, Error>; type Item = Result<Rc<Frame>>;
type IntoIter = TRRTrajectoryIterator; type IntoIter = TRRTrajectoryIterator;
fn into_iter(mut self) -> Self::IntoIter { fn into_iter(mut self) -> Self::IntoIter {
@@ -87,7 +86,7 @@ pub struct TRRTrajectoryIterator {
} }
impl Iterator for TRRTrajectoryIterator { impl Iterator for TRRTrajectoryIterator {
type Item = Result<Rc<Frame>, Error>; type Item = Result<Rc<Frame>>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
// Reuse old frame // Reuse old frame

View File

@@ -75,12 +75,59 @@ use c_abi::xdrfile::XDRFILE;
use c_abi::xdrfile_trr; use c_abi::xdrfile_trr;
use c_abi::xdrfile_xtc; use c_abi::xdrfile_xtc;
use failure::{err_msg, Error};
use lazy_init::Lazy; use lazy_init::Lazy;
use std::cell::Cell; use std::cell::Cell;
use std::ffi::CString; use std::ffi::CString;
use std::path::Path; use std::path::Path;
#[derive(Debug, Clone)]
pub enum Error {
CouldNotOpenFile(std::path::PathBuf, FileMode),
CouldNotReadAtomNumber(u32),
CouldNotRead(u32),
CouldNotWrite(u32),
CouldNotFlush(u32),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use Error::*;
match self {
CouldNotOpenFile(path, mode) => write!(
f,
"Failed to open file at {path:?} with mode {mode:?}",
path = path,
mode = mode
),
CouldNotReadAtomNumber(code) => write!(
f,
"Failed to read atom number from trajectory: C API returned error code {}",
code
),
CouldNotRead(code) => write!(
f,
"Failed to read trajectory: C API returned error code {}",
code
),
CouldNotWrite(code) => write!(
f,
"Failed to write trajectory: C API returned error code {}",
code
),
CouldNotFlush(code) => write!(
f,
"Failed to flush trajectory: C API returned error code {}",
code
),
}
}
}
impl std::error::Error for Error {}
type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone)]
pub enum FileMode { pub enum FileMode {
Write, Write,
Append, Append,
@@ -110,7 +157,7 @@ struct XDRFile {
} }
impl XDRFile { impl XDRFile {
pub fn open(path: &Path, filemode: FileMode) -> Result<XDRFile, Error> { pub fn open(path: &Path, filemode: FileMode) -> Result<XDRFile> {
let path_p = path_to_cstring(path).into_raw(); let path_p = path_to_cstring(path).into_raw();
let mode_p = CString::new(filemode.value()).unwrap().into_raw(); let mode_p = CString::new(filemode.value()).unwrap().into_raw();
@@ -126,7 +173,7 @@ impl XDRFile {
}) })
} else { } else {
// Something went wrong. But the C api does not tell us what // Something went wrong. But the C api does not tell us what
Err(err_msg("Failed to open trajectory file")) Err(Error::CouldNotOpenFile(path.into(), filemode))
} }
} }
} }
@@ -144,27 +191,27 @@ impl Drop for XDRFile {
/// The trajectory trait defines shared methods for xtc and trr trajectories /// The trajectory trait defines shared methods for xtc and trr trajectories
pub trait Trajectory { pub trait Trajectory {
/// Read the next step of the trajectory into the frame object /// Read the next step of the trajectory into the frame object
fn read(&mut self, frame: &mut Frame) -> Result<(), Error>; fn read(&mut self, frame: &mut Frame) -> Result<()>;
/// Write the frame to the trajectory file /// Write the frame to the trajectory file
fn write(&mut self, frame: &Frame) -> Result<(), Error>; fn write(&mut self, frame: &Frame) -> Result<()>;
/// Flush the trajectory file /// Flush the trajectory file
fn flush(&mut self) -> Result<(), Error>; fn flush(&mut self) -> Result<()>;
/// Get the number of atoms from the give trajectory /// Get the number of atoms from the give trajectory
fn get_num_atoms(&mut self) -> Result<u32, Error>; fn get_num_atoms(&mut self) -> Result<u32>;
} }
/// Read/Write XTC Trajectories /// Read/Write XTC Trajectories
pub struct XTCTrajectory { pub struct XTCTrajectory {
handle: XDRFile, handle: XDRFile,
precision: Cell<f32>, // internal mutability required for read method precision: Cell<f32>, // internal mutability required for read method
num_atoms: Lazy<Result<u32, Error>>, num_atoms: Lazy<Result<u32>>,
} }
impl XTCTrajectory { impl XTCTrajectory {
pub fn open(path: &Path, filemode: FileMode) -> Result<XTCTrajectory, Error> { pub fn open(path: &Path, filemode: FileMode) -> Result<XTCTrajectory> {
let xdr = XDRFile::open(path, filemode)?; let xdr = XDRFile::open(path, filemode)?;
Ok(XTCTrajectory { Ok(XTCTrajectory {
handle: xdr, handle: xdr,
@@ -175,7 +222,7 @@ impl XTCTrajectory {
} }
impl Trajectory for XTCTrajectory { impl Trajectory for XTCTrajectory {
fn read(&mut self, frame: &mut Frame) -> Result<(), Error> { fn read(&mut self, frame: &mut Frame) -> Result<()> {
unsafe { unsafe {
// C lib requires an i32 to be passed, but step is exposed it as u32 // C lib requires an i32 to be passed, but step is exposed it as u32
// (A step cannot be negative, can it?). So we need to create a step // (A step cannot be negative, can it?). So we need to create a step
@@ -193,15 +240,12 @@ impl Trajectory for XTCTrajectory {
frame.step = step as u32; frame.step = step as u32;
match code { match code {
xdrfile::exdrOK => Ok(()), xdrfile::exdrOK => Ok(()),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotRead(code)),
"Failed to read trajectory. Error code: {}",
code
))),
} }
} }
} }
fn write(&mut self, frame: &Frame) -> Result<(), Error> { fn write(&mut self, frame: &Frame) -> Result<()> {
unsafe { unsafe {
let code = xdrfile_xtc::write_xtc( let code = xdrfile_xtc::write_xtc(
self.handle.xdrfile, self.handle.xdrfile,
@@ -214,29 +258,24 @@ impl Trajectory for XTCTrajectory {
) as u32; ) as u32;
match code { match code {
xdrfile::exdrOK => Ok(()), xdrfile::exdrOK => Ok(()),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotWrite(code)),
"Failed to write trajectory. Error code: {}",
code
))),
} }
} }
} }
fn flush(&mut self) -> Result<(), Error> { fn flush(&mut self) -> Result<()> {
unsafe { unsafe {
let code = xdr_seek::xdr_flush(self.handle.xdrfile) as u32; let code = xdr_seek::xdr_flush(self.handle.xdrfile) as u32;
match code { match code {
xdrfile::exdrOK => Ok(()), xdrfile::exdrOK => Ok(()),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotFlush(code)),
"Failed to flush trajectory. Error code: {}",
code
))),
} }
} }
} }
fn get_num_atoms(&mut self) -> Result<u32, Error> { fn get_num_atoms(&mut self) -> Result<u32> {
let result = self.num_atoms.get_or_create(|| { self.num_atoms
.get_or_create(|| {
let mut num_atoms: i32 = 0; let mut num_atoms: i32 = 0;
unsafe { unsafe {
let path = CString::new(self.handle.path.as_str()).unwrap(); let path = CString::new(self.handle.path.as_str()).unwrap();
@@ -245,29 +284,22 @@ impl Trajectory for XTCTrajectory {
xdrfile_xtc::read_xtc_natoms(path_p, &mut num_atoms as *const i32) as u32; xdrfile_xtc::read_xtc_natoms(path_p, &mut num_atoms as *const i32) as u32;
match code { match code {
xdrfile::exdrOK => Ok(num_atoms as u32), xdrfile::exdrOK => Ok(num_atoms as u32),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotReadAtomNumber(code)),
"Failed to read atom number from trajectory. Error code: {}",
code
))),
} }
} }
}); })
match result { .clone()
Ok(val) => Ok(*val),
// ugly hack because failure::Error is not "Clone"
Err(err) => Err(err_msg(format!("{}", err))),
}
} }
} }
/// Read/Write TRR Trajectories /// Read/Write TRR Trajectories
pub struct TRRTrajectory { pub struct TRRTrajectory {
handle: XDRFile, handle: XDRFile,
num_atoms: Lazy<Result<u32, Error>>, num_atoms: Lazy<Result<u32>>,
} }
impl TRRTrajectory { impl TRRTrajectory {
pub fn open(path: &Path, filemode: FileMode) -> Result<TRRTrajectory, Error> { pub fn open(path: &Path, filemode: FileMode) -> Result<TRRTrajectory> {
let xdr = XDRFile::open(path, filemode)?; let xdr = XDRFile::open(path, filemode)?;
Ok(TRRTrajectory { Ok(TRRTrajectory {
handle: xdr, handle: xdr,
@@ -277,7 +309,7 @@ impl TRRTrajectory {
} }
impl Trajectory for TRRTrajectory { impl Trajectory for TRRTrajectory {
fn read(&mut self, frame: &mut Frame) -> Result<(), Error> { fn read(&mut self, frame: &mut Frame) -> Result<()> {
unsafe { unsafe {
// C lib requires an i32 to be passed, but step is exposed it as u32 // C lib requires an i32 to be passed, but step is exposed it as u32
// (A step cannot be negative, can it?). So we need to create a step // (A step cannot be negative, can it?). So we need to create a step
@@ -299,15 +331,12 @@ impl Trajectory for TRRTrajectory {
frame.step = step as u32; frame.step = step as u32;
match code { match code {
xdrfile::exdrOK => Ok(()), xdrfile::exdrOK => Ok(()),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotRead(code)),
"Failed to read trajectory. Error code: {}",
code
))),
} }
} }
} }
fn write(&mut self, frame: &Frame) -> Result<(), Error> { fn write(&mut self, frame: &Frame) -> Result<()> {
unsafe { unsafe {
let code = xdrfile_trr::write_trr( let code = xdrfile_trr::write_trr(
self.handle.xdrfile, self.handle.xdrfile,
@@ -322,29 +351,24 @@ impl Trajectory for TRRTrajectory {
) as u32; ) as u32;
match code { match code {
xdrfile::exdrOK => Ok(()), xdrfile::exdrOK => Ok(()),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotWrite(code)),
"Failed to write trajectory. Error code: {}",
code
))),
} }
} }
} }
fn flush(&mut self) -> Result<(), Error> { fn flush(&mut self) -> Result<()> {
unsafe { unsafe {
let code = xdr_seek::xdr_flush(self.handle.xdrfile) as u32; let code = xdr_seek::xdr_flush(self.handle.xdrfile) as u32;
match code { match code {
xdrfile::exdrOK => Ok(()), xdrfile::exdrOK => Ok(()),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotFlush(code)),
"Failed to flush trajectory. Error code: {}",
code
))),
} }
} }
} }
fn get_num_atoms(&mut self) -> Result<u32, Error> { fn get_num_atoms(&mut self) -> Result<u32> {
let result = self.num_atoms.get_or_create(|| { self.num_atoms
.get_or_create(|| {
let mut num_atoms: i32 = 0; let mut num_atoms: i32 = 0;
unsafe { unsafe {
let path = CString::new(self.handle.path.as_str()).unwrap(); let path = CString::new(self.handle.path.as_str()).unwrap();
@@ -353,18 +377,11 @@ impl Trajectory for TRRTrajectory {
xdrfile_trr::read_trr_natoms(path_p, &mut num_atoms as *const i32) as u32; xdrfile_trr::read_trr_natoms(path_p, &mut num_atoms as *const i32) as u32;
match code { match code {
xdrfile::exdrOK => Ok(num_atoms as u32), xdrfile::exdrOK => Ok(num_atoms as u32),
_ => Err(err_msg(format!( _ => Err(Error::CouldNotReadAtomNumber(code)),
"Failed to read atom number from trajectory. Error code: {}",
code
))),
} }
} }
}); })
match result { .clone()
Ok(val) => Ok(*val),
// ugly hack because failure::Error is not "Clone"
Err(err) => Err(err_msg(format!("{}", err))),
}
} }
} }