From ae19428cd54404668162dcfd0d6cf0b04de222ed Mon Sep 17 00:00:00 2001 From: _cry64 Date: Fri, 27 Mar 2026 15:35:02 +1000 Subject: [PATCH] finish ErrorContext::set_err --- nixide/src/errors/context.rs | 53 +++++++++++++++++----------------- nixide/src/errors/nix_error.rs | 15 ++++++++++ 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/nixide/src/errors/context.rs b/nixide/src/errors/context.rs index 39b1ea6..6ea266e 100644 --- a/nixide/src/errors/context.rs +++ b/nixide/src/errors/context.rs @@ -26,7 +26,7 @@ use std::ffi::c_void; use std::ptr::NonNull; use super::{NixError, NixideResult}; -use crate::stdext::CCharPtrExt as _; +use crate::stdext::{AsCPtr as _, CCharPtrExt as _}; use crate::sys; use crate::util::panic_issue_call_failed; use crate::util::wrap; @@ -62,8 +62,8 @@ use crate::util::wrappers::AsInnerPtr; /// ```c /// assert(*(nix_err*)ctx == NIX_OK); /// ``` +/// pub(crate) struct ErrorContext { - // XXX: TODO: add a RwLock to this (maybe Arc? or is that excessive?) inner: NonNull, } @@ -92,6 +92,7 @@ impl Into> for &ErrorContext { /// /// This function will panic in the event that `value != sys::nix_err_NIX_OK` /// but that `context.get_code() == sys::nix_err_NIX_OK` + /// fn into(self) -> NixideResult<()> { let inner = match self.get_err() { Some(err) => err, @@ -132,37 +133,22 @@ impl ErrorContext { /// /// Returns an error if no memory can be allocated for /// the underlying [sys::nix_c_context] struct. + /// pub fn new() -> Self { match NonNull::new(unsafe { sys::nix_c_context_create() }) { Some(inner) => ErrorContext { inner }, None => panic!("[nixide] CRITICAL FAILURE: Out-Of-Memory condition reached - `sys::nix_c_context_create` allocation failed!"), } - - // Initialize required libraries - // XXX: TODO: move this to a separate init function (maybe a Nix::init() function) - // unsafe { - // NixErrorCode::from( - // sys::nix_libutil_init(ctx.inner.as_ptr()), - // "nix_libutil_init", - // )?; - // NixErrorCode::from( - // sys::nix_libstore_init(ctx.inner.as_ptr()), - // "nix_libstore_init", - // )?; - // NixErrorCode::from( - // sys::nix_libexpr_init(ctx.inner.as_ptr()), - // "nix_libexpr_init", - // )?; - // }; } /// Check the error code and return an error if it's not `NIX_OK`. + /// pub fn peak(&self) -> NixideResult<()> { self.into() } - /// /// Equivalent to running `self.peak()` then `self.clear()` + /// pub fn pop(&mut self) -> NixideResult<()> { self.peak().and_then(|_| Ok(self.clear())) } @@ -204,24 +190,32 @@ impl ErrorContext { /// } /// ``` /// - pub fn set_err(&self, err: NixError, msg: &str) { + #[allow(unused)] + pub fn set_err(&self, err: NixError, msg: &str) -> NixideResult<()> { let ptr = unsafe { self.as_ptr() }; assert!(!ptr.is_null(), ""); - sys::nix_set_err_msg(ptr, err.into()) + unsafe { + sys::nix_set_err_msg(ptr, err.err_code(), msg.as_c_ptr()?); + } + + Ok(()) } /// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise. /// /// # Nix C++ API Internals + /// /// ```cpp /// nix_err nix_err_code(const nix_c_context * read_context) /// { /// return read_context->last_err_code; /// } /// ``` + /// /// This function **never fails**. - pub(super) fn get_err(&self) -> Option { + /// + fn get_err(&self) -> Option { let err = unsafe { sys::nix_err_code(self.as_ptr()) }; match err { @@ -233,6 +227,7 @@ impl ErrorContext { /// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise. /// /// # Nix C++ API Internals + /// /// ```cpp /// const char * nix_err_msg(nix_c_context * context, const nix_c_context * read_context, unsigned int * n) /// { @@ -249,6 +244,7 @@ impl ErrorContext { /// ``` /// /// # Note + /// /// On failure [sys::nix_err_name] does the following if the error /// has the error code [sys::nix_err_NIX_OK]: /// ```cpp @@ -257,7 +253,8 @@ impl ErrorContext { /// ``` /// Hence we can just test whether the returned pointer is a `NULL` pointer, /// and avoid passing in a [sys::nix_c_context] struct. - pub(super) fn get_msg(&self) -> Option { + /// + fn get_msg(&self) -> Option { let ctx = ErrorContext::new(); unsafe { // NOTE: an Err here only occurs when `self.get_code() == Ok(())` @@ -298,12 +295,14 @@ impl ErrorContext { /// `nix_set_err_msg` will cause undefined behaviour if `context` is a null pointer (see below) /// due to [https://github.com/rust-lang/rust-bindgen/issues/1208]. /// So we should never assigned it [std::ptr::null_mut]. + /// /// ```cpp /// if (context == nullptr) { /// throw nix::Error("Nix C api error: %s", msg); /// } /// ``` - pub(super) fn get_nix_err_name(&self) -> Option { + /// + fn get_nix_err_name(&self) -> Option { #[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe` unsafe { // NOTE: an Err here only occurs when "Last error was not a nix error" @@ -349,12 +348,14 @@ impl ErrorContext { /// `nix_set_err_msg` will cause undefined behaviour if `context` is a null pointer (see below) /// due to [https://github.com/rust-lang/rust-bindgen/issues/1208]. /// So we should never assigned it [std::ptr::null_mut]. + /// /// ```cpp /// if (context == nullptr) { /// throw nix::Error("Nix C api error: %s", msg); /// } /// ``` - pub(super) fn get_nix_err_info_msg(&self) -> Option { + /// + fn get_nix_err_info_msg(&self) -> Option { #[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe` unsafe { // NOTE: an Err here only occurs when "Last error was not a nix error" diff --git a/nixide/src/errors/nix_error.rs b/nixide/src/errors/nix_error.rs index 5e3938e..1d67312 100644 --- a/nixide/src/errors/nix_error.rs +++ b/nixide/src/errors/nix_error.rs @@ -113,3 +113,18 @@ impl Display for NixError { } } } + +impl NixError { + pub fn err_code(&self) -> sys::nix_err { + match self { + NixError::Overflow => sys::nix_err_NIX_ERR_OVERFLOW, + NixError::KeyNotFound(_) => sys::nix_err_NIX_ERR_NIX_ERROR, + NixError::ExprEval { + name: _, + info_msg: _, + } => sys::nix_err_NIX_ERR_NIX_ERROR, + NixError::Unknown => sys::nix_err_NIX_ERR_UNKNOWN, + NixError::Undocumented(err) => err.clone(), + } + } +}