Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor error handling #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
73 changes: 29 additions & 44 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::fmt;
use std::ffi::NulError;
use ::Augeas;
use ::util::ptr_to_string;
use augeas_sys::*;

#[derive(Clone,PartialEq,Debug)]
Expand All @@ -28,20 +26,21 @@ impl fmt::Display for Error {
}
}

#[derive(Clone,PartialEq,Eq,Debug,Default)]
#[derive(Clone,PartialEq,Eq,Debug)]
pub struct AugeasError {
pub code : ErrorCode,
pub message : Option<String>,
pub minor_message : Option<String>,
pub details : Option<String>
pub code: ErrorCode,
pub message: Option<String>,
pub minor_message: Option<String>,
pub details: Option<String>
}

impl AugeasError {
pub fn new_no_mem(message: impl Into<String>) -> AugeasError {
AugeasError {
code : ErrorCode::NoMem,
message : Some(message.into()),
.. Default::default()
code: ErrorCode::NoMem,
message: Some(message.into()),
minor_message: None,
details: None,
}
}
}
Expand All @@ -50,28 +49,29 @@ impl ::std::error::Error for AugeasError {
fn description(&self) -> &str {
match self.message {
None => "No description",
Some(ref s) => s
Some(ref s) => s,
}
}
}

fn maybe_write(f: &mut fmt::Formatter, opt: &Option<String>) -> fmt::Result {
match *opt {
Some(ref s) => write!(f, " {}\n", s),
None => Ok(())
}
}

impl fmt::Display for AugeasError {
// Write
// augeas error:{code}:{message}
// {minor_message}
// {details}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let m = self.message.as_ref().map(String::as_ref).unwrap_or("");
write!(f, "augeas error:{:?}:{}\n", self.code, m).
and(maybe_write(f, &self.minor_message)).
and(maybe_write(f, &self.details))
let message = self.message.as_ref().map(String::as_ref).unwrap_or("");
writeln!(f, "augeas error:{:?}:{}", self.code, message)?;

if let Some(minor_message) = &self.minor_message {
writeln!(f, " {}", minor_message)?;
}

if let Some(details) = &self.details {
writeln!(f, " {}", details)?;
}

Ok(())
}
}

Expand All @@ -81,26 +81,15 @@ impl From<NulError> for Error {
}
}

impl <'a> From<&'a Augeas> for Error {
fn from(aug: &'a Augeas) -> Error {
let err = unsafe { aug_error(aug.ptr) };
let err = ErrorCode::from_raw(err as _);
let msg = unsafe { ptr_to_string(aug_error_message(aug.ptr)) };
let mmsg = unsafe { ptr_to_string(aug_error_minor_message(aug.ptr)) };
let det = unsafe { ptr_to_string(aug_error_details(aug.ptr)) };
Error::Augeas(AugeasError {
code: err,
message: msg,
minor_message: mmsg,
details: det
})
impl From<AugeasError> for Error {
fn from(err: AugeasError) -> Error {
Error::Augeas(err)
}
}

#[repr(C)]
#[derive(Copy,Clone,PartialEq,Eq,Debug)]
pub enum ErrorCode {
NoError,
NoMem,
Internal,
PathExpr,
Expand All @@ -120,9 +109,9 @@ pub enum ErrorCode {

impl ErrorCode {
#[allow(non_upper_case_globals)]
pub fn from_raw(code: aug_errcode_t) -> ErrorCode {
match code {
aug_errcode_t_AUG_NOERROR => ErrorCode::NoError,
pub fn from_raw(code: aug_errcode_t) -> Option<ErrorCode> {
Some(match code {
aug_errcode_t_AUG_NOERROR => return None,
aug_errcode_t_AUG_ENOMEM => ErrorCode::NoMem,
aug_errcode_t_AUG_EINTERNAL => ErrorCode::Internal,
aug_errcode_t_AUG_EPATHX => ErrorCode::PathExpr,
Expand All @@ -138,10 +127,6 @@ impl ErrorCode {
aug_errcode_t_AUG_ELABEL => ErrorCode::Label,
aug_errcode_t_AUG_ECPDESC => ErrorCode::CopyDescendant,
_ => ErrorCode::Unknown,
}
})
}
}

impl Default for ErrorCode {
fn default() -> ErrorCode { ErrorCode::NoError }
}
57 changes: 32 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,34 +55,35 @@ impl Augeas {
let ref path = CString::new(path)?;
let path = path.as_ptr();
let mut value: *const c_char = ptr::null_mut();

unsafe { aug_get(self.ptr, path, &mut value) };
self.check_error()?;

let value = unsafe { ptr_to_string(value) };

self.make_result(value)
Ok(value)
}

pub fn label(&self, path: &str) -> Result<Option<String>> {
pub fn label(&self, path: &str) -> Result<Option<String>> {
let path_c = CString::new(path)?;
let mut return_value: *const c_char = ptr::null();
let mut value: *const c_char = ptr::null();

unsafe {
aug_label(self.ptr, path_c.as_ptr(), &mut return_value)
};
unsafe { aug_label(self.ptr, path_c.as_ptr(), &mut value) };
self.check_error()?;

self.make_result(unsafe { ptr_to_string(return_value) })
let value = unsafe { ptr_to_string(value) };

Ok(value)
}

pub fn matches(&self, path: &str) -> Result<Vec<String>> {
let c_path = CString::new(path)?;

unsafe {
let mut matches_ptr: *mut *mut c_char = ptr::null_mut();

let nmatches = aug_match(self.ptr, c_path.as_ptr(), &mut matches_ptr);
self.check_error()?;

if nmatches < 0 {
return self.make_error()
}
let matches_vec = (0 .. nmatches).map(|i| {
let match_ptr: *const c_char = transmute(*matches_ptr.offset(i as isize));
let str = ptr_to_string(match_ptr).unwrap();
Expand All @@ -98,32 +99,38 @@ impl Augeas {

pub fn save(&mut self) -> Result<()> {
unsafe { aug_save(self.ptr) };
self.make_result(())
self.check_error()?;

Ok(())
}

pub fn set(&mut self, path: &str, value: &str) -> Result<()> {
let path_c = CString::new(path.as_bytes())?;
let value_c = CString::new(value.as_bytes())?;

unsafe { aug_set(self.ptr, path_c.as_ptr(), value_c.as_ptr()) };
self.make_result(())
self.check_error()?;

Ok(())
}
}

impl Augeas {
fn make_error<T>(&self) -> Result<T> {
Err(Error::from(self))
fn check_error(&self) -> std::result::Result<(), AugeasError> {
self.error().map(Err).unwrap_or(Ok(()))
}

fn make_result<T>(&self, v : T) -> Result<T> {
fn error(&self) -> Option<AugeasError> {
let err = unsafe { aug_error(self.ptr) };
let err = ErrorCode::from_raw(err as _);

if err != ErrorCode::NoError {
return self.make_error();
}

Ok(v)
let err = ErrorCode::from_raw(err as _)?;
let msg = unsafe { ptr_to_string(aug_error_message(self.ptr)) };
let mmsg = unsafe { ptr_to_string(aug_error_minor_message(self.ptr)) };
let det = unsafe { ptr_to_string(aug_error_details(self.ptr)) };

Some(AugeasError {
code: err,
message: msg,
minor_message: mmsg,
details: det
})
}
}

Expand Down