diff --git a/nixide/src/errors/context.rs b/nixide/src/errors/context.rs index 91c5cec..1b4c4a5 100644 --- a/nixide/src/errors/context.rs +++ b/nixide/src/errors/context.rs @@ -24,11 +24,11 @@ use std::ffi::c_uint; use std::ptr::NonNull; -use super::NixideError; +use super::{NixError, NixideError, NixideResult}; use crate::sys; use crate::util::bindings::wrap_libnix_string_callback; use crate::util::wrappers::AsInnerPtr; -use crate::util::CCharPtrNixExt; +use crate::util::{panic_issue_call_failed, CCharPtrNixExt}; /// This object stores error state. /// @@ -71,6 +71,34 @@ impl AsInnerPtr for ErrorContext { } } +impl Into> for &ErrorContext { + fn into(self) -> NixideResult<()> { + let inner = self.get_err().ok_?; + let msg = self.get_msg()?; + + let err = match inner { + sys::nix_err_NIX_OK => unreachable!(), + + sys::nix_err_NIX_ERR_OVERFLOW => NixError::Overflow, + sys::nix_err_NIX_ERR_KEY => NixError::KeyNotFound(None), + sys::nix_err_NIX_ERR_NIX_ERROR => NixError::ExprEval { + name: self + .get_nix_err_name() + .unwrap_or_else(|| panic_issue_call_failed!()), + + info_msg: self + .get_nix_err_info_msg() + .unwrap_or_else(|| panic_issue_call_failed!()), + }, + + sys::nix_err_NIX_ERR_UNKNOWN => NixError::Unknown, + err => NixError::Undocumented(err), + }; + + Some(new_nixide_error!(NixError, inner, err, msg)) + } +} + impl ErrorContext { /// Create a new error context. /// @@ -103,18 +131,19 @@ impl ErrorContext { } /// Check the error code and return an error if it's not `NIX_OK`. - pub fn peak(&self) -> Option { - NixideError::from_error_context(self) + pub fn peak(&self) -> NixideResult<()> { + match self.into() { + Some(err) => Err(err), + None => Ok(()), + } } /// /// Equivalent to running `self.peak()` then `self.clear()` - pub fn pop(&mut self) -> Option { - self.get_err().and_then(|_| { - let error = self.peak(); - self.clear(); - error - }) + pub fn pop(&mut self) -> NixideResult<()> { + let error = self.peak(); + self.clear(); + error } /// # Nix C++ API Internals @@ -151,10 +180,9 @@ impl ErrorContext { pub(super) fn get_err(&self) -> Option { let err = unsafe { sys::nix_err_code(self.as_ptr()) }; - if err == sys::nix_err_NIX_OK { - None - } else { - Some(err) + match err { + sys::nix_err_NIX_OK => None, + _ => Some(err), } } diff --git a/nixide/src/errors/error.rs b/nixide/src/errors/error.rs index b47694e..986527f 100644 --- a/nixide/src/errors/error.rs +++ b/nixide/src/errors/error.rs @@ -94,7 +94,7 @@ impl NixideError { /// # Panics /// /// This function will panic in the event that `context.get_err() == Some(err) && err == sys::nix_err_NIX_OK` - /// since `nixide::ErrorContext::get_err` is expected to return `None` to indicate `sys::ni_err_NIX_OK`. + /// since `nixide::ErrorContext::get_err` is expected to return `None` to indicate `sys::nix_err_NIX_OK`. /// /// /// This function will panic in the event that `value != sys::nix_err_NIX_OK` @@ -103,7 +103,6 @@ impl NixideError { let inner = context.get_err()?; let msg = context.get_msg()?; - #[allow(nonstandard_style)] let err = match inner { sys::nix_err_NIX_OK => unreachable!(), diff --git a/nixide/src/lib.rs b/nixide/src/lib.rs index 90ffab7..0ef0b16 100644 --- a/nixide/src/lib.rs +++ b/nixide/src/lib.rs @@ -3,6 +3,7 @@ pub(crate) mod errors; mod expr; mod flake; +mod stdext; mod store; pub(crate) mod util; mod verbosity; diff --git a/nixide/src/stdext/cchar_ptr_ext.rs b/nixide/src/stdext/cchar_ptr_ext.rs new file mode 100644 index 0000000..cd8bbfb --- /dev/null +++ b/nixide/src/stdext/cchar_ptr_ext.rs @@ -0,0 +1,30 @@ +use std::ffi::{c_char, CStr}; +use std::slice::from_raw_parts; +use std::str::{from_utf8, Utf8Error}; + +pub trait CCharPtrExt { + fn to_utf8_string(self) -> Result>; + + fn to_utf8_string_n(self, n: usize) -> Result>; +} + +impl CCharPtrExt for *const c_char { + fn to_utf8_string(self) -> Result> { + if self.is_null() { + return Err(None); + } + let cstr = unsafe { CStr::from_ptr(self) }; + match cstr.to_str() { + Ok(s) => Ok(s.to_owned()), + Err(err) => Err(Some(err)), + } + } + + fn to_utf8_string_n(self, n: usize) -> Result> { + if self.is_null() || n == 0 { + return Err(None); + } + let bytes = unsafe { from_raw_parts(self.cast::(), n as usize) }; + from_utf8(bytes).map(str::to_string).map_err(Some) + } +} diff --git a/nixide/src/stdext/mod.rs b/nixide/src/stdext/mod.rs new file mode 100644 index 0000000..fe17913 --- /dev/null +++ b/nixide/src/stdext/mod.rs @@ -0,0 +1,4 @@ +mod cchar_ptr_ext; + +pub(crate) use cchar_ptr_ext::CCharPtrExt; +pub(crate) use stdext::*; diff --git a/nixide/src/util/cchar_nix_ext.rs b/nixide/src/util/cchar_nix_ext.rs deleted file mode 100644 index 82b9fc8..0000000 --- a/nixide/src/util/cchar_nix_ext.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::ffi::{c_char, CStr}; -use std::slice::from_raw_parts; -use std::str::from_utf8; - -use crate::errors::{new_nixide_error, NixideError}; - -pub trait CCharPtrNixExt { - fn to_utf8_string(self) -> Result; - - fn to_utf8_string_sized(self, n: usize) -> Result; -} - -impl CCharPtrNixExt for *const c_char { - fn to_utf8_string(self) -> Result { - if self.is_null() { - return Err(new_nixide_error!(NullPtr)); - } - - let result = unsafe { CStr::from_ptr(self).to_str() }; - match result { - Ok(msg_str) => Ok(msg_str.to_string()), - Err(_) => Err(new_nixide_error!(StringNulByte)), - } - } - - fn to_utf8_string_sized(self, n: usize) -> Result { - if !self.is_null() && n > 0 { - let bytes = unsafe { from_raw_parts(self.cast::(), n as usize) }; - from_utf8(bytes) - .ok() - .map(|s| s.to_string()) - .ok_or(new_nixide_error!(NullPtr)) - } else { - Err(new_nixide_error!(NullPtr)) - } - } -}