Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub enum Error {
value: String,
target: &'static str,
},
/// Attempted to perform an unsupported operation given the file mode
WrongMode { mode: FileMode, task: ErrorTask },
}

impl Error {
Expand Down Expand Up @@ -132,6 +134,12 @@ impl std::fmt::Display for Error {
value = value,
target = target
),
Error::WrongMode { mode, task } => write!(
f,
"{task} is impossible with file mode {mode:?}",
mode = mode,
task = task.uppercase_first(),
),
}
}
}
Expand All @@ -151,6 +159,14 @@ pub enum ErrorTask {
Seek,
}

impl ErrorTask {
fn uppercase_first(&self) -> String {
let mut s = format!("{}", self);
&mut s[0..1].make_ascii_uppercase();
s
}
}

impl std::fmt::Display for ErrorTask {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self {
Expand Down
92 changes: 89 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ use std::os::raw::{c_float, c_int};
use std::path::{Path, PathBuf};

/// File Mode for accessing trajectories.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum FileMode {
Write,
Append,
Expand Down Expand Up @@ -148,7 +148,6 @@ fn check_code(code: impl Into<ErrorCode>, task: ErrorTask) -> Option<Error> {
/// A safe wrapper around the c implementation of an XDRFile
struct XDRFile {
xdrfile: *mut XDRFILE,
#[allow(dead_code)]
filemode: FileMode,
path: PathBuf,
}
Expand Down Expand Up @@ -232,7 +231,6 @@ pub trait Trajectory {

/// Get the number of atoms from the give trajectory
fn get_num_atoms(&mut self) -> Result<usize>;

}

/// Handle to Read/Write XTC Trajectories
Expand Down Expand Up @@ -266,10 +264,23 @@ impl XTCTrajectory {
pub fn open_write(path: impl AsRef<Path>) -> Result<Self> {
Self::open(path, FileMode::Write)
}

/// The mode the current file is open in
pub fn file_mode(&self) -> FileMode {
self.handle.filemode
}
}

impl Trajectory for XTCTrajectory {
fn read(&mut self, frame: &mut Frame) -> Result<()> {
match self.handle.filemode {
FileMode::Read => Ok(()),
mode => Err(Error::WrongMode {
mode,
task: ErrorTask::Read,
}),
}?;

let mut step: c_int = 0;

let num_atoms = self
Expand Down Expand Up @@ -298,6 +309,14 @@ impl Trajectory for XTCTrajectory {
}

fn write(&mut self, frame: &Frame) -> Result<()> {
match self.handle.filemode {
FileMode::Append | FileMode::Write => Ok(()),
mode @ FileMode::Read => Err(Error::WrongMode {
mode,
task: ErrorTask::Write,
}),
}?;

unsafe {
let code = xdrfile_xtc::write_xtc(
self.handle.xdrfile,
Expand All @@ -317,6 +336,14 @@ impl Trajectory for XTCTrajectory {
}

fn flush(&mut self) -> Result<()> {
match self.handle.filemode {
FileMode::Append | FileMode::Write => Ok(()),
mode @ FileMode::Read => Err(Error::WrongMode {
mode,
task: ErrorTask::Flush,
}),
}?;

unsafe {
let code = xdr_seek::xdr_flush(self.handle.xdrfile);
if let Some(err) = check_code(code, ErrorTask::Flush) {
Expand Down Expand Up @@ -392,10 +419,23 @@ impl TRRTrajectory {
pub fn open_write(path: impl AsRef<Path>) -> Result<Self> {
Self::open(path, FileMode::Write)
}

/// The mode the current file is open in
pub fn file_mode(&self) -> FileMode {
self.handle.filemode
}
}

impl Trajectory for TRRTrajectory {
fn read(&mut self, frame: &mut Frame) -> Result<()> {
match self.handle.filemode {
FileMode::Read => Ok(()),
mode => Err(Error::WrongMode {
mode,
task: ErrorTask::Read,
}),
}?;

let mut step: c_int = 0;
let mut lambda: c_float = 0.0;

Expand Down Expand Up @@ -427,6 +467,14 @@ impl Trajectory for TRRTrajectory {
}

fn write(&mut self, frame: &Frame) -> Result<()> {
match self.handle.filemode {
FileMode::Append | FileMode::Write => Ok(()),
mode @ FileMode::Read => Err(Error::WrongMode {
mode,
task: ErrorTask::Write,
}),
}?;

unsafe {
let code = xdrfile_trr::write_trr(
self.handle.xdrfile,
Expand All @@ -448,6 +496,14 @@ impl Trajectory for TRRTrajectory {
}

fn flush(&mut self) -> Result<()> {
match self.handle.filemode {
FileMode::Append | FileMode::Write => Ok(()),
mode @ FileMode::Read => Err(Error::WrongMode {
mode,
task: ErrorTask::Flush,
}),
}?;

unsafe {
let code = xdr_seek::xdr_flush(self.handle.xdrfile);
if let Some(err) = check_code(code, ErrorTask::Flush) {
Expand Down Expand Up @@ -501,6 +557,36 @@ mod tests {
use std::io::Write;
use tempfile::NamedTempFile;

#[test]
fn test_read_writemode_xtc() -> Result<(), Box<dyn std::error::Error>> {
let tempfile = NamedTempFile::new().expect("Could not create temporary file");
let tmp_path = tempfile.path();

let natoms = 2;
let frame = Frame {
step: 5,
time: 2.0,
box_vector: [[1.0, 2.0, 3.0], [2.0, 1.0, 3.0], [3.0, 2.0, 1.0]],
coords: vec![[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]],
};
let mut f = XTCTrajectory::open_write(&tmp_path)?;
f.write(&frame)?;
f.flush()?;

f.seek(SeekFrom::Start(0))?;

let mut new_frame = Frame::with_len(natoms);

let read_status = f.read(&mut new_frame);
let expected = Error::WrongMode {
mode: FileMode::Write,
task: ErrorTask::Read,
};

assert_eq!(Err(expected), read_status);
Ok(())
}

#[test]
fn test_read_write_xtc() -> Result<()> {
let tempfile = NamedTempFile::new().expect("Could not create temporary file");
Expand Down