diff --git a/.gitignore b/.gitignore index d42ac36..e6857d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ # Nix -/result -/result-* +result +result-* # Rust /target - -# Helix -/.helix diff --git a/nixide-sys/tests/eval.rs b/nixide-sys/tests/eval.rs index c417850..742b4d0 100644 --- a/nixide-sys/tests/eval.rs +++ b/nixide-sys/tests/eval.rs @@ -1,4 +1,3 @@ -#![cfg(feature = "nix-expr-c")] #![cfg(test)] use std::{ diff --git a/nixide-sys/tests/flake.rs b/nixide-sys/tests/flake.rs index d9f67c8..01fed21 100644 --- a/nixide-sys/tests/flake.rs +++ b/nixide-sys/tests/flake.rs @@ -1,4 +1,3 @@ -#![cfg(feature = "nix-flake-c")] #![cfg(test)] use std::ptr; diff --git a/nixide-sys/tests/memory.rs b/nixide-sys/tests/memory.rs index 4ac8702..229b6bd 100644 --- a/nixide-sys/tests/memory.rs +++ b/nixide-sys/tests/memory.rs @@ -1,4 +1,3 @@ -#![cfg(feature = "nix-expr-c")] #![cfg(test)] use std::ffi::CString; diff --git a/nixide-sys/tests/primop.rs b/nixide-sys/tests/primop.rs index 257faaf..ecfacf8 100644 --- a/nixide-sys/tests/primop.rs +++ b/nixide-sys/tests/primop.rs @@ -1,4 +1,3 @@ -#![cfg(feature = "nix-expr-c")] #![cfg(test)] use std::{ diff --git a/nixide-sys/tests/store.rs b/nixide-sys/tests/store.rs index b1c8171..bb12a33 100644 --- a/nixide-sys/tests/store.rs +++ b/nixide-sys/tests/store.rs @@ -1,4 +1,3 @@ -#![cfg(feature = "nix-store-c")] #![cfg(test)] use std::{ffi::CString, ptr}; diff --git a/nixide/src/errors/context.rs b/nixide/src/errors/context.rs index 6ea266e..39b1ea6 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::{AsCPtr as _, CCharPtrExt as _}; +use crate::stdext::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,7 +92,6 @@ 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, @@ -133,22 +132,37 @@ 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()` /// + /// Equivalent to running `self.peak()` then `self.clear()` pub fn pop(&mut self) -> NixideResult<()> { self.peak().and_then(|_| Ok(self.clear())) } @@ -190,32 +204,24 @@ impl ErrorContext { /// } /// ``` /// - #[allow(unused)] - pub fn set_err(&self, err: NixError, msg: &str) -> NixideResult<()> { + pub fn set_err(&self, err: NixError, msg: &str) { let ptr = unsafe { self.as_ptr() }; assert!(!ptr.is_null(), ""); - unsafe { - sys::nix_set_err_msg(ptr, err.err_code(), msg.as_c_ptr()?); - } - - Ok(()) + sys::nix_set_err_msg(ptr, err.into()) } /// 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**. - /// - fn get_err(&self) -> Option { + pub(super) fn get_err(&self) -> Option { let err = unsafe { sys::nix_err_code(self.as_ptr()) }; match err { @@ -227,7 +233,6 @@ 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) /// { @@ -244,7 +249,6 @@ 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 @@ -253,8 +257,7 @@ 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. - /// - fn get_msg(&self) -> Option { + pub(super) fn get_msg(&self) -> Option { let ctx = ErrorContext::new(); unsafe { // NOTE: an Err here only occurs when `self.get_code() == Ok(())` @@ -295,14 +298,12 @@ 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); /// } /// ``` - /// - fn get_nix_err_name(&self) -> Option { + pub(super) 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" @@ -348,14 +349,12 @@ 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); /// } /// ``` - /// - fn get_nix_err_info_msg(&self) -> Option { + pub(super) 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 1d67312..5e3938e 100644 --- a/nixide/src/errors/nix_error.rs +++ b/nixide/src/errors/nix_error.rs @@ -113,18 +113,3 @@ 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(), - } - } -} diff --git a/nixide/src/expr/realised_string.rs b/nixide/src/expr/realised_string.rs index a3dbc7c..5be5f8b 100644 --- a/nixide/src/expr/realised_string.rs +++ b/nixide/src/expr/realised_string.rs @@ -13,9 +13,9 @@ use crate::{EvalState, NixideResult, StorePath}; pub struct RealisedString { inner: NonNull, + // pub path: LazyCell StorePath>>, pub path: StorePath, - pub children: - LazyArray StorePath>, usize) -> StorePath>, + pub children: LazyArray StorePath>, usize) -> StorePath>>, } impl AsInnerPtr for RealisedString { @@ -88,6 +88,7 @@ impl RealisedString { Ok(Self { inner, path: Self::parse_path(inner.as_ptr(), state), + // children: LazyArray::new(size, delegate as fn(usize) -> StorePath), children: LazyArray:: StorePath>>::new( size, Box::new(delegate), diff --git a/nixide/src/lib.rs b/nixide/src/lib.rs index 2acbdd1..dd127c6 100644 --- a/nixide/src/lib.rs +++ b/nixide/src/lib.rs @@ -11,13 +11,14 @@ mod version; #[cfg(feature = "expr")] mod expr; -#[cfg(feature = "flake")] -mod flake; #[cfg(feature = "store")] mod store; +#[cfg(feature = "flake")] +mod flake; + pub use errors::{NixError, NixideError, NixideResult}; -pub use verbosity::{set_verbosity, NixVerbosity}; +pub use verbosity::NixVerbosity; pub use version::NixVersion; #[cfg(feature = "expr")] diff --git a/nixide/src/stdext/cchar_ptr_ext.rs b/nixide/src/stdext/cchar_ptr_ext.rs index 0a91b86..733ed98 100644 --- a/nixide/src/stdext/cchar_ptr_ext.rs +++ b/nixide/src/stdext/cchar_ptr_ext.rs @@ -6,10 +6,8 @@ use crate::errors::new_nixide_error; use crate::NixideResult; pub trait AsCPtr { - #[allow(unused)] fn as_c_ptr(&self) -> NixideResult<*const T>; - #[allow(unused)] fn into_c_ptr(self) -> NixideResult<*mut T>; } @@ -33,10 +31,8 @@ where } pub trait CCharPtrExt { - #[allow(unused)] fn to_utf8_string(self) -> NixideResult; - #[allow(unused)] fn to_utf8_string_n(self, n: usize) -> NixideResult; } diff --git a/nixide/src/stdext/mod.rs b/nixide/src/stdext/mod.rs index d30c295..fe17913 100644 --- a/nixide/src/stdext/mod.rs +++ b/nixide/src/stdext/mod.rs @@ -1,4 +1,4 @@ mod cchar_ptr_ext; -pub(crate) use cchar_ptr_ext::{AsCPtr, CCharPtrExt}; +pub(crate) use cchar_ptr_ext::CCharPtrExt; pub(crate) use stdext::*; diff --git a/nixide/src/util/lazy_array.rs b/nixide/src/util/lazy_array.rs index 6b4b1a5..2808314 100644 --- a/nixide/src/util/lazy_array.rs +++ b/nixide/src/util/lazy_array.rs @@ -1,11 +1,12 @@ -use std::cell::{Ref, RefCell}; +use std::cell::RefCell; +use std::rc::Rc; #[derive(Debug)] pub struct LazyArray where F: Fn(usize) -> T, { - inner: RefCell>>, + inner: Rc>>>, size: usize, delegate: F, } @@ -21,25 +22,58 @@ where } LazyArray { - inner: RefCell::new(vec), + inner: Rc::new(RefCell::new(vec)), size, delegate, } } - /// Returns `None` if `index >= self.size` otherwise always succeeds + /// Returns `None` if `index < self.size` otherwise always succeeds /// (unless of course the callback you supply panics). /// - pub fn get<'a>(&'a mut self, index: usize) -> Option>> { - let borrowed = self.inner.borrow(); + // pub fn get(&mut self, index: usize) -> Option<&T> { + // // let x = self.inner.get(index).copied().and_then(|value| match value { + // // Some(value) => Some(value), + // // None => { + // // // store the value first + // // let value = (self.delegate)(index); + // // self.inner[index] = Some(value); + // // // now get a reference to it + // // if let Some(v) = &self.inner[index] { + // // return Some(v); + // // } + // // None + // // } + // // }) + // match self.inner.clone().borrow().get(index) { + // Some(Some(value)) => Some(value), + // Some(None) => { + // let mut inner = self.inner.clone().borrow_mut(); + // // store the value first + // inner[index] = Some((self.delegate)(index)); + + // // now get a reference to it + // inner[index].as_ref() + // } + // None => None, + // } + // } + pub fn get(&mut self, index: usize) -> Option> { if index >= self.size { return None; - } else if borrowed[index].is_none() { - let value = (self.delegate)(index); - self.inner.borrow_mut()[index] = Some(value); } - Some(Ref::map(borrowed, |v| &v[index])) + // let inner = self.inner.borrow(); + if let Some(value) = self.inner.borrow()[index].as_ref() { + return Some(Rc::new(value)); + } + + // drop(inner); // explicitly drop the borrow + + let value = (self.delegate)(index); + self.inner.borrow_mut()[index] = Some(value); + + Some(Rc::new(self.inner.borrow()[index].unwrap())) } } diff --git a/nixide/src/util/wrappers.rs b/nixide/src/util/wrappers.rs index 938187c..c3e4b07 100644 --- a/nixide/src/util/wrappers.rs +++ b/nixide/src/util/wrappers.rs @@ -6,7 +6,6 @@ pub trait AsInnerPtr { /// Although this function isn't inherently `unsafe`, it is /// marked as such intentionally to force calls to be wrapped /// in `unsafe` blocks for clarity. - #[allow(unused)] unsafe fn as_ptr(&self) -> *mut T; /// Returns a shared reference to the inner `libnix` C struct. @@ -18,7 +17,6 @@ pub trait AsInnerPtr { /// Although this function isn't inherently `unsafe`, it is /// marked as such intentionally to force calls to be wrapped /// in `unsafe` blocks for clarity. - #[allow(unused)] unsafe fn as_ref(&self) -> &T; /// Returns a unique reference to the inner `libnix` C struct. @@ -30,6 +28,5 @@ pub trait AsInnerPtr { /// Although this function isn't inherently `unsafe`, it is /// marked as such intentionally to force calls to be wrapped /// in `unsafe` blocks for clarity. - #[allow(unused)] unsafe fn as_mut(&mut self) -> &mut T; }