mirror of
https://github.com/dnlbauer/xdrfile.git
synced 2026-09-11 06:35:30 +00:00
Returned Error to being an enum, as other fields were unused
This commit is contained in:
118
src/errors.rs
118
src/errors.rs
@@ -3,23 +3,26 @@ use crate::FileMode;
|
|||||||
use crate::Frame;
|
use crate::Frame;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
/// Error type for the xdrfile library
|
/// Error type for the xdrfile library
|
||||||
pub struct Error {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
kind: ErrorKind,
|
pub enum Error {
|
||||||
source: Option<Box<Error>>,
|
/// An error code from the C API
|
||||||
|
CApiError { code: ErrorCode, task: ErrorTask },
|
||||||
|
/// Passed in a frame of the wrong size
|
||||||
|
WrongSizeFrame { expected: usize, found: usize },
|
||||||
|
/// C API failed to open a file (No return code provided)
|
||||||
|
CouldNotOpen { path: PathBuf, mode: FileMode },
|
||||||
|
/// A path could not be converted to &OsStr, probably because it is invalid unicode
|
||||||
|
InvalidOsStr,
|
||||||
|
/// A path could not be converted to &CStr because it had a null byte
|
||||||
|
NullInStr(std::ffi::NulError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
/// Get the task being attempted when the error was returned
|
|
||||||
pub fn kind(&self) -> &ErrorKind {
|
|
||||||
&self.kind
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the error code returned by the C API, if any
|
/// Get the error code returned by the C API, if any
|
||||||
pub fn code(&self) -> Option<ErrorCode> {
|
pub fn code(&self) -> Option<ErrorCode> {
|
||||||
if let ErrorKind::CApiError { code, .. } = self.kind {
|
if let Error::CApiError { code, .. } = self {
|
||||||
Some(code)
|
Some(*code)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -27,8 +30,8 @@ impl Error {
|
|||||||
|
|
||||||
/// Get the task being attempted when the C API returned an error, if any
|
/// Get the task being attempted when the C API returned an error, if any
|
||||||
pub fn task(&self) -> Option<ErrorTask> {
|
pub fn task(&self) -> Option<ErrorTask> {
|
||||||
if let ErrorKind::CApiError { task, .. } = self.kind {
|
if let Error::CApiError { task, .. } = self {
|
||||||
Some(task)
|
Some(*task)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -37,7 +40,6 @@ impl Error {
|
|||||||
/// True if the error is an end of file error, false otherwise
|
/// True if the error is an end of file error, false otherwise
|
||||||
pub fn is_eof(&self) -> bool {
|
pub fn is_eof(&self) -> bool {
|
||||||
self.code().map_or(false, |e| e.is_eof())
|
self.code().map_or(false, |e| e.is_eof())
|
||||||
| self.source.as_ref().map_or(false, |e| e.is_eof())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an error code and output value from a C call to a Result
|
/// Convert an error code and output value from a C call to a Result
|
||||||
@@ -51,86 +53,50 @@ impl Error {
|
|||||||
if let ErrorCode::ExdrOk = code {
|
if let ErrorCode::ExdrOk = code {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(Self {
|
Err(Self::CApiError { code, task })
|
||||||
kind: ErrorKind::CApiError { code, task },
|
|
||||||
source: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Into<ErrorKind>> From<K> for Error {
|
|
||||||
fn from(kind: K) -> Self {
|
|
||||||
Self {
|
|
||||||
kind: kind.into(),
|
|
||||||
source: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
self.kind.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)> {
|
||||||
if let Some(err) = &self.source {
|
use Error::*;
|
||||||
Some(err)
|
match &self {
|
||||||
} else {
|
|
||||||
use ErrorKind::*;
|
|
||||||
match &self.kind {
|
|
||||||
NullInStr(err) => Some(err),
|
NullInStr(err) => Some(err),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
impl From<std::ffi::NulError> for Error {
|
||||||
pub enum ErrorKind {
|
|
||||||
/// An error code from the C API
|
|
||||||
CApiError { code: ErrorCode, task: ErrorTask },
|
|
||||||
/// Passed in a frame of the wrong size
|
|
||||||
WrongSizeFrame { expected: usize, found: usize },
|
|
||||||
/// C API failed to open a file (No return code provided)
|
|
||||||
CouldNotOpen { path: PathBuf, mode: FileMode },
|
|
||||||
/// A path could not be converted to &OsStr, probably because it is invalid unicode
|
|
||||||
InvalidOsStr,
|
|
||||||
/// A path could not be converted to &CStr because it had a null byte
|
|
||||||
NullInStr(std::ffi::NulError),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<std::ffi::NulError> for ErrorKind {
|
|
||||||
fn from(err: std::ffi::NulError) -> Self {
|
fn from(err: std::ffi::NulError) -> Self {
|
||||||
Self::NullInStr(err)
|
Self::NullInStr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(&Path, FileMode)> for ErrorKind {
|
impl From<(&Path, FileMode)> for Error {
|
||||||
fn from(value: (&Path, FileMode)) -> Self {
|
fn from(value: (&Path, FileMode)) -> Self {
|
||||||
let (path, mode) = value;
|
let (path, mode) = value;
|
||||||
ErrorKind::CouldNotOpen {
|
Error::CouldNotOpen {
|
||||||
path: path.to_owned(),
|
path: path.to_owned(),
|
||||||
mode,
|
mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(&Frame, usize)> for ErrorKind {
|
impl From<(&Frame, usize)> for Error {
|
||||||
fn from(value: (&Frame, usize)) -> Self {
|
fn from(value: (&Frame, usize)) -> Self {
|
||||||
let (frame, num_atoms) = value;
|
let (frame, num_atoms) = value;
|
||||||
ErrorKind::WrongSizeFrame {
|
Error::WrongSizeFrame {
|
||||||
expected: num_atoms,
|
expected: num_atoms,
|
||||||
found: frame.coords.len(),
|
found: frame.coords.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for ErrorKind {
|
impl std::fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
use ErrorKind::*;
|
use Error::*;
|
||||||
match &self {
|
match &self {
|
||||||
CApiError { code, task } => write!(
|
CApiError { code, task } => write!(
|
||||||
f,
|
f,
|
||||||
@@ -263,58 +229,40 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_eof() {
|
fn test_is_eof() {
|
||||||
use ErrorKind::CApiError;
|
use Error::CApiError;
|
||||||
let error = Error {
|
let error = CApiError {
|
||||||
kind: CApiError {
|
|
||||||
code: c_abi::xdrfile::exdrENDOFFILE.into(),
|
code: c_abi::xdrfile::exdrENDOFFILE.into(),
|
||||||
task: ErrorTask::Read,
|
task: ErrorTask::Read,
|
||||||
},
|
|
||||||
source: None,
|
|
||||||
};
|
};
|
||||||
assert!(error.is_eof());
|
assert!(error.is_eof());
|
||||||
|
|
||||||
let error = Error {
|
let error = CApiError {
|
||||||
kind: CApiError {
|
|
||||||
code: ErrorCode::ExdrEndOfFile,
|
code: ErrorCode::ExdrEndOfFile,
|
||||||
task: ErrorTask::Read,
|
task: ErrorTask::Read,
|
||||||
},
|
|
||||||
source: None,
|
|
||||||
};
|
};
|
||||||
assert!(error.is_eof());
|
assert!(error.is_eof());
|
||||||
|
|
||||||
let error = Error {
|
let error = CApiError {
|
||||||
kind: CApiError {
|
|
||||||
code: (c_abi::xdrfile::exdrENDOFFILE + 1).into(),
|
code: (c_abi::xdrfile::exdrENDOFFILE + 1).into(),
|
||||||
task: ErrorTask::Read,
|
task: ErrorTask::Read,
|
||||||
},
|
|
||||||
source: None,
|
|
||||||
};
|
};
|
||||||
assert!(!error.is_eof());
|
assert!(!error.is_eof());
|
||||||
|
|
||||||
let error = Error {
|
let error = CApiError {
|
||||||
kind: CApiError {
|
|
||||||
code: 0.into(),
|
code: 0.into(),
|
||||||
task: ErrorTask::Read,
|
task: ErrorTask::Read,
|
||||||
},
|
|
||||||
source: None,
|
|
||||||
};
|
};
|
||||||
assert!(!error.is_eof());
|
assert!(!error.is_eof());
|
||||||
|
|
||||||
let error = Error {
|
let error = CApiError {
|
||||||
kind: CApiError {
|
|
||||||
code: 255.into(),
|
code: 255.into(),
|
||||||
task: ErrorTask::Read,
|
task: ErrorTask::Read,
|
||||||
},
|
|
||||||
source: None,
|
|
||||||
};
|
};
|
||||||
assert!(!error.is_eof());
|
assert!(!error.is_eof());
|
||||||
|
|
||||||
let error = Error {
|
let error = Error::CouldNotOpen {
|
||||||
kind: ErrorKind::CouldNotOpen {
|
|
||||||
path: PathBuf::from("not/a/file"),
|
path: PathBuf::from("not/a/file"),
|
||||||
mode: FileMode::Read,
|
mode: FileMode::Read,
|
||||||
},
|
|
||||||
source: None,
|
|
||||||
};
|
};
|
||||||
assert!(!error.is_eof());
|
assert!(!error.is_eof());
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/lib.rs
20
src/lib.rs
@@ -101,11 +101,7 @@ impl FileMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn path_to_cstring(path: impl AsRef<Path>) -> Result<CString> {
|
fn path_to_cstring(path: impl AsRef<Path>) -> Result<CString> {
|
||||||
use ErrorKind::InvalidOsStr;
|
let s = path.as_ref().to_str().ok_or_else(|| Error::InvalidOsStr)?;
|
||||||
let s = path
|
|
||||||
.as_ref()
|
|
||||||
.to_str()
|
|
||||||
.ok_or_else(|| Error::from(InvalidOsStr))?;
|
|
||||||
CString::new(s).map_err(|e| Error::from(e))
|
CString::new(s).map_err(|e| Error::from(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +496,7 @@ mod tests {
|
|||||||
|
|
||||||
let result = xtc_traj.read(&mut frame);
|
let result = xtc_traj.read(&mut frame);
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
assert!(if let ErrorKind::WrongSizeFrame { .. } = e.kind() {
|
assert!(if let Error::WrongSizeFrame { .. } = e {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -516,9 +512,9 @@ mod tests {
|
|||||||
let result_invalid = path_to_cstring(PathBuf::from("invalid/\0path"));
|
let result_invalid = path_to_cstring(PathBuf::from("invalid/\0path"));
|
||||||
|
|
||||||
if let Err(err) = result_invalid {
|
if let Err(err) = result_invalid {
|
||||||
match err.kind() {
|
match err {
|
||||||
ErrorKind::NullInStr(_) => (),
|
Error::NullInStr(_) => (),
|
||||||
ErrorKind::InvalidOsStr => (),
|
Error::InvalidOsStr => (),
|
||||||
_ => panic!("Improper error type for path_to_cstring"),
|
_ => panic!("Improper error type for path_to_cstring"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -537,13 +533,13 @@ mod tests {
|
|||||||
|
|
||||||
let path = Path::new(&file_name);
|
let path = Path::new(&file_name);
|
||||||
if let Err(e) = XDRFile::open(file_name, FileMode::Read) {
|
if let Err(e) = XDRFile::open(file_name, FileMode::Read) {
|
||||||
if let ErrorKind::CouldNotOpen {
|
if let Error::CouldNotOpen {
|
||||||
path: err_path,
|
path: err_path,
|
||||||
mode: err_mode,
|
mode: err_mode,
|
||||||
} = e.kind()
|
} = e
|
||||||
{
|
{
|
||||||
assert_eq!(path, err_path);
|
assert_eq!(path, err_path);
|
||||||
assert_eq!(FileMode::Read, *err_mode)
|
assert_eq!(FileMode::Read, err_mode)
|
||||||
} else {
|
} else {
|
||||||
panic!("Wrong Error type")
|
panic!("Wrong Error type")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user