mirror of
https://github.com/dnlbauer/xdrfile.git
synced 2026-09-10 22:25:30 +00:00
Unified conversion errors and improved messages
This commit is contained in:
@@ -2,41 +2,29 @@ use crate::c_abi;
|
|||||||
use crate::FileMode;
|
use crate::FileMode;
|
||||||
use crate::Frame;
|
use crate::Frame;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use std::os::raw::c_int;
|
|
||||||
use std::path::{Path, PathBuf};
|
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)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// An error code from the C API
|
/// An error code from the C API
|
||||||
CApiError {
|
CApiError { code: ErrorCode, task: ErrorTask },
|
||||||
code: ErrorCode,
|
|
||||||
task: ErrorTask,
|
|
||||||
},
|
|
||||||
/// Passed in a frame of the wrong size
|
/// Passed in a frame of the wrong size
|
||||||
WrongSizeFrame {
|
WrongSizeFrame { expected: usize, found: usize },
|
||||||
expected: usize,
|
|
||||||
found: usize,
|
|
||||||
},
|
|
||||||
/// C API failed to open a file (No return code provided)
|
/// C API failed to open a file (No return code provided)
|
||||||
CouldNotOpen {
|
CouldNotOpen { path: PathBuf, mode: FileMode },
|
||||||
path: PathBuf,
|
|
||||||
mode: FileMode,
|
|
||||||
},
|
|
||||||
/// A path could not be converted to &OsStr
|
/// A path could not be converted to &OsStr
|
||||||
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),
|
||||||
|
/// Checking the number of atoms failed while reading a frame
|
||||||
CouldNotCheckNAtoms(Box<Error>),
|
CouldNotCheckNAtoms(Box<Error>),
|
||||||
/// Step was out of range for usize on this platform
|
/// Error for an out-of-range numeric conversion
|
||||||
StepOutOfRange(i32),
|
OutOfRange {
|
||||||
/// natoms was out of range for usize on this platform
|
name: &'static str,
|
||||||
NumAtomsOutOfRange(c_int),
|
|
||||||
/// A numeric cast from `value` failed during `task`
|
|
||||||
CastToCintFailed {
|
|
||||||
source: std::num::TryFromIntError,
|
|
||||||
task: ErrorTask,
|
task: ErrorTask,
|
||||||
value: usize,
|
value: String,
|
||||||
|
target: &'static str,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +63,6 @@ impl std::error::Error for Error {
|
|||||||
match &self {
|
match &self {
|
||||||
NullInStr(err) => Some(err),
|
NullInStr(err) => Some(err),
|
||||||
CouldNotCheckNAtoms(err) => Some(err.as_ref()),
|
CouldNotCheckNAtoms(err) => Some(err.as_ref()),
|
||||||
CastToCintFailed { source, .. } => Some(source),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,21 +124,18 @@ impl std::fmt::Display for Error {
|
|||||||
CouldNotCheckNAtoms(_err) => {
|
CouldNotCheckNAtoms(_err) => {
|
||||||
write!(f, "Failed to read number of atoms in trajectory file")
|
write!(f, "Failed to read number of atoms in trajectory file")
|
||||||
}
|
}
|
||||||
StepOutOfRange(n) => write!(
|
OutOfRange {
|
||||||
|
name,
|
||||||
|
task,
|
||||||
|
value,
|
||||||
|
target,
|
||||||
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"Illegal step size while reading trajectory: Failed to cast {} to usize.",
|
"Illegal {name} while {task}: Failed to cast {value} to {target}",
|
||||||
n
|
name = name,
|
||||||
),
|
task = task,
|
||||||
NumAtomsOutOfRange(n) => write!(
|
|
||||||
f,
|
|
||||||
"Illegal number of atoms while reading trajectory: Failed to cast {} to usize.",
|
|
||||||
n
|
|
||||||
),
|
|
||||||
CastToCintFailed { value, task, .. } => write!(
|
|
||||||
f,
|
|
||||||
"Numeric cast from {value}:usize to C int failed while {task}",
|
|
||||||
value = value,
|
value = value,
|
||||||
task = task
|
target = target
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
60
src/lib.rs
60
src/lib.rs
@@ -109,14 +109,24 @@ fn path_to_cstring(path: impl AsRef<Path>) -> Result<CString> {
|
|||||||
Ok(CString::new(s)?)
|
Ok(CString::new(s)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_c_int(value: usize, task: ErrorTask) -> Result<c_int> {
|
fn to<I, O>(value: I, task: ErrorTask, name: &'static str) -> Result<O>
|
||||||
value.try_into().map_err(|e| Error::CastToCintFailed {
|
where
|
||||||
source: e,
|
I: TryInto<O> + std::fmt::Display + Copy,
|
||||||
value,
|
{
|
||||||
|
value.try_into().map_err(|_| Error::OutOfRange {
|
||||||
|
name,
|
||||||
|
value: format!("{}", &value),
|
||||||
|
target: std::any::type_name::<O>(),
|
||||||
task,
|
task,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! to {
|
||||||
|
($value:expr, $task:expr) => {
|
||||||
|
to($value, $task, stringify!($value))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert an error code from a C call to an Error
|
/// Convert an error code from a C call to an Error
|
||||||
///
|
///
|
||||||
/// `code` should be an integer return code returned from the C API.
|
/// `code` should be an integer return code returned from the C API.
|
||||||
@@ -267,7 +277,7 @@ impl Trajectory for XTCTrajectory {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let code = xdrfile_xtc::read_xtc(
|
let code = xdrfile_xtc::read_xtc(
|
||||||
self.handle.xdrfile,
|
self.handle.xdrfile,
|
||||||
to_c_int(num_atoms, ErrorTask::Read)?,
|
to!(num_atoms, ErrorTask::Read)?,
|
||||||
&mut step,
|
&mut step,
|
||||||
&mut frame.time,
|
&mut frame.time,
|
||||||
&mut frame.box_vector,
|
&mut frame.box_vector,
|
||||||
@@ -277,7 +287,7 @@ impl Trajectory for XTCTrajectory {
|
|||||||
if let Some(err) = check_code(code, ErrorTask::Read) {
|
if let Some(err) = check_code(code, ErrorTask::Read) {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
frame.step = usize::try_from(step).map_err(|_| Error::StepOutOfRange(step))?;
|
frame.step = to!(step, ErrorTask::ReadNumAtoms)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,8 +296,8 @@ impl Trajectory for XTCTrajectory {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let code = xdrfile_xtc::write_xtc(
|
let code = xdrfile_xtc::write_xtc(
|
||||||
self.handle.xdrfile,
|
self.handle.xdrfile,
|
||||||
to_c_int(frame.len(), ErrorTask::Write)?,
|
to!(frame.num_atoms(), ErrorTask::Write)?,
|
||||||
to_c_int(frame.step, ErrorTask::Write)?,
|
to!(frame.step, ErrorTask::Write)?,
|
||||||
frame.time,
|
frame.time,
|
||||||
&frame.box_vector,
|
&frame.box_vector,
|
||||||
frame.coords.as_ptr(),
|
frame.coords.as_ptr(),
|
||||||
@@ -327,7 +337,7 @@ impl Trajectory for XTCTrajectory {
|
|||||||
if let Some(err) = check_code(code, ErrorTask::ReadNumAtoms) {
|
if let Some(err) = check_code(code, ErrorTask::ReadNumAtoms) {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
usize::try_from(num_atoms).map_err(|_| Error::NumAtomsOutOfRange(num_atoms))
|
to!(num_atoms, ErrorTask::ReadNumAtoms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -394,7 +404,7 @@ impl Trajectory for TRRTrajectory {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let code = xdrfile_trr::read_trr(
|
let code = xdrfile_trr::read_trr(
|
||||||
self.handle.xdrfile,
|
self.handle.xdrfile,
|
||||||
to_c_int(num_atoms, ErrorTask::Read)?,
|
to!(num_atoms, ErrorTask::Read)?,
|
||||||
&mut step,
|
&mut step,
|
||||||
&mut frame.time,
|
&mut frame.time,
|
||||||
&mut lambda,
|
&mut lambda,
|
||||||
@@ -406,7 +416,7 @@ impl Trajectory for TRRTrajectory {
|
|||||||
if let Some(err) = check_code(code, ErrorTask::Read) {
|
if let Some(err) = check_code(code, ErrorTask::Read) {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
frame.step = usize::try_from(step).map_err(|_| Error::StepOutOfRange(step))?;
|
frame.step = to!(step, ErrorTask::ReadNumAtoms)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,8 +425,8 @@ impl Trajectory for TRRTrajectory {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let code = xdrfile_trr::write_trr(
|
let code = xdrfile_trr::write_trr(
|
||||||
self.handle.xdrfile,
|
self.handle.xdrfile,
|
||||||
to_c_int(frame.len(), ErrorTask::Write)?,
|
to!(frame.len(), ErrorTask::Write)?,
|
||||||
to_c_int(frame.step, ErrorTask::Write)?,
|
to!(frame.step, ErrorTask::Write)?,
|
||||||
frame.time,
|
frame.time,
|
||||||
0.0,
|
0.0,
|
||||||
&frame.box_vector,
|
&frame.box_vector,
|
||||||
@@ -457,7 +467,7 @@ impl Trajectory for TRRTrajectory {
|
|||||||
if let Some(err) = check_code(code, ErrorTask::ReadNumAtoms) {
|
if let Some(err) = check_code(code, ErrorTask::ReadNumAtoms) {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
usize::try_from(num_atoms).map_err(|_| Error::NumAtomsOutOfRange(num_atoms))
|
to!(num_atoms, ErrorTask::ReadNumAtoms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -794,22 +804,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_to_c_int() -> Result<()> {
|
fn test_to() -> Result<()> {
|
||||||
assert_eq!(24234 as c_int, to_c_int(24234_usize, ErrorTask::Read)?);
|
assert_eq!(24234_i32, to!(24234_usize, ErrorTask::Write)?);
|
||||||
|
|
||||||
let try_from_int_err = match u8::try_from(-1) {
|
let expected: Result<i32> = Err(Error::OutOfRange {
|
||||||
Err(e) => e,
|
name: "3_294_967_295_usize",
|
||||||
_ => panic!("Conversion from -1 to u8 succeeded"),
|
|
||||||
};
|
|
||||||
let expected = Error::CastToCintFailed {
|
|
||||||
source: try_from_int_err,
|
|
||||||
task: ErrorTask::Write,
|
task: ErrorTask::Write,
|
||||||
value: 3_294_967_295_usize,
|
value: "3294967295".to_string(),
|
||||||
};
|
target: "i32",
|
||||||
assert_eq!(
|
});
|
||||||
Err(expected),
|
assert_eq!(expected, to!(3_294_967_295_usize, ErrorTask::Write));
|
||||||
to_c_int(3_294_967_295_usize, ErrorTask::Write)
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user