finish ErrorContext::set_err

This commit is contained in:
do butterflies cry? 2026-03-27 15:35:02 +10:00
parent 5930db8233
commit ae19428cd5
Signed by: cry
GPG key ID: F68745A836CA0412
2 changed files with 42 additions and 26 deletions

View file

@ -26,7 +26,7 @@ use std::ffi::c_void;
use std::ptr::NonNull; use std::ptr::NonNull;
use super::{NixError, NixideResult}; use super::{NixError, NixideResult};
use crate::stdext::CCharPtrExt as _; use crate::stdext::{AsCPtr as _, CCharPtrExt as _};
use crate::sys; use crate::sys;
use crate::util::panic_issue_call_failed; use crate::util::panic_issue_call_failed;
use crate::util::wrap; use crate::util::wrap;
@ -62,8 +62,8 @@ use crate::util::wrappers::AsInnerPtr;
/// ```c /// ```c
/// assert(*(nix_err*)ctx == NIX_OK); /// assert(*(nix_err*)ctx == NIX_OK);
/// ``` /// ```
///
pub(crate) struct ErrorContext { pub(crate) struct ErrorContext {
// XXX: TODO: add a RwLock to this (maybe Arc<RwLock>? or is that excessive?)
inner: NonNull<sys::nix_c_context>, inner: NonNull<sys::nix_c_context>,
} }
@ -92,6 +92,7 @@ impl Into<NixideResult<()>> for &ErrorContext {
/// ///
/// This function will panic in the event that `value != sys::nix_err_NIX_OK` /// This function will panic in the event that `value != sys::nix_err_NIX_OK`
/// but that `context.get_code() == sys::nix_err_NIX_OK` /// but that `context.get_code() == sys::nix_err_NIX_OK`
///
fn into(self) -> NixideResult<()> { fn into(self) -> NixideResult<()> {
let inner = match self.get_err() { let inner = match self.get_err() {
Some(err) => err, Some(err) => err,
@ -132,37 +133,22 @@ impl ErrorContext {
/// ///
/// Returns an error if no memory can be allocated for /// Returns an error if no memory can be allocated for
/// the underlying [sys::nix_c_context] struct. /// the underlying [sys::nix_c_context] struct.
///
pub fn new() -> Self { pub fn new() -> Self {
match NonNull::new(unsafe { sys::nix_c_context_create() }) { match NonNull::new(unsafe { sys::nix_c_context_create() }) {
Some(inner) => ErrorContext { inner }, Some(inner) => ErrorContext { inner },
None => panic!("[nixide] CRITICAL FAILURE: Out-Of-Memory condition reached - `sys::nix_c_context_create` allocation failed!"), 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`. /// Check the error code and return an error if it's not `NIX_OK`.
///
pub fn peak(&self) -> NixideResult<()> { pub fn peak(&self) -> NixideResult<()> {
self.into() self.into()
} }
///
/// Equivalent to running `self.peak()` then `self.clear()` /// Equivalent to running `self.peak()` then `self.clear()`
///
pub fn pop(&mut self) -> NixideResult<()> { pub fn pop(&mut self) -> NixideResult<()> {
self.peak().and_then(|_| Ok(self.clear())) 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() }; let ptr = unsafe { self.as_ptr() };
assert!(!ptr.is_null(), ""); 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. /// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise.
/// ///
/// # Nix C++ API Internals /// # Nix C++ API Internals
///
/// ```cpp /// ```cpp
/// nix_err nix_err_code(const nix_c_context * read_context) /// nix_err nix_err_code(const nix_c_context * read_context)
/// { /// {
/// return read_context->last_err_code; /// return read_context->last_err_code;
/// } /// }
/// ``` /// ```
///
/// This function **never fails**. /// This function **never fails**.
pub(super) fn get_err(&self) -> Option<sys::nix_err> { ///
fn get_err(&self) -> Option<sys::nix_err> {
let err = unsafe { sys::nix_err_code(self.as_ptr()) }; let err = unsafe { sys::nix_err_code(self.as_ptr()) };
match err { match err {
@ -233,6 +227,7 @@ impl ErrorContext {
/// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise. /// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise.
/// ///
/// # Nix C++ API Internals /// # Nix C++ API Internals
///
/// ```cpp /// ```cpp
/// const char * nix_err_msg(nix_c_context * context, const nix_c_context * read_context, unsigned int * n) /// 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 /// # Note
///
/// On failure [sys::nix_err_name] does the following if the error /// On failure [sys::nix_err_name] does the following if the error
/// has the error code [sys::nix_err_NIX_OK]: /// has the error code [sys::nix_err_NIX_OK]:
/// ```cpp /// ```cpp
@ -257,7 +253,8 @@ impl ErrorContext {
/// ``` /// ```
/// Hence we can just test whether the returned pointer is a `NULL` pointer, /// Hence we can just test whether the returned pointer is a `NULL` pointer,
/// and avoid passing in a [sys::nix_c_context] struct. /// and avoid passing in a [sys::nix_c_context] struct.
pub(super) fn get_msg(&self) -> Option<String> { ///
fn get_msg(&self) -> Option<String> {
let ctx = ErrorContext::new(); let ctx = ErrorContext::new();
unsafe { unsafe {
// NOTE: an Err here only occurs when `self.get_code() == Ok(())` // 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) /// `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]. /// due to [https://github.com/rust-lang/rust-bindgen/issues/1208].
/// So we should never assigned it [std::ptr::null_mut]. /// So we should never assigned it [std::ptr::null_mut].
///
/// ```cpp /// ```cpp
/// if (context == nullptr) { /// if (context == nullptr) {
/// throw nix::Error("Nix C api error: %s", msg); /// throw nix::Error("Nix C api error: %s", msg);
/// } /// }
/// ``` /// ```
pub(super) fn get_nix_err_name(&self) -> Option<String> { ///
fn get_nix_err_name(&self) -> Option<String> {
#[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe` #[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe`
unsafe { unsafe {
// NOTE: an Err here only occurs when "Last error was not a nix error" // 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) /// `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]. /// due to [https://github.com/rust-lang/rust-bindgen/issues/1208].
/// So we should never assigned it [std::ptr::null_mut]. /// So we should never assigned it [std::ptr::null_mut].
///
/// ```cpp /// ```cpp
/// if (context == nullptr) { /// if (context == nullptr) {
/// throw nix::Error("Nix C api error: %s", msg); /// throw nix::Error("Nix C api error: %s", msg);
/// } /// }
/// ``` /// ```
pub(super) fn get_nix_err_info_msg(&self) -> Option<String> { ///
fn get_nix_err_info_msg(&self) -> Option<String> {
#[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe` #[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe`
unsafe { unsafe {
// NOTE: an Err here only occurs when "Last error was not a nix error" // NOTE: an Err here only occurs when "Last error was not a nix error"

View file

@ -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(),
}
}
}