diff --git a/flake.nix b/flake.nix index 49560e3..30f7a1d 100644 --- a/flake.nix +++ b/flake.nix @@ -24,7 +24,6 @@ allowUnfree = false; allowBroken = false; overlays = builtins.attrValues self.overlays or {}; - # config.replaceStdenv = {pkgs}: with pkgs; llvmPackages_21.stdenv; }; forAllSystems = f: @@ -61,19 +60,13 @@ packages = with pkgs; [ rustc llvmPackages.lld - llvmPackages.lldb - # lldb + lldb cargo cargo-c cargo-llvm-cov cargo-nextest - clang # DEBUG - clang-tools # DEBUG - - libcxx - rust-analyzer-unwrapped (rustfmt.override {asNightly = true;}) clippy diff --git a/nixide-sys/build.rs b/nixide-sys/build.rs index 1fee802..23c0e7c 100644 --- a/nixide-sys/build.rs +++ b/nixide-sys/build.rs @@ -1,5 +1,5 @@ +use std::env; use std::path::PathBuf; -use std::{env, fs}; use bindgen::callbacks::ParseCallbacks; @@ -18,26 +18,31 @@ impl ParseCallbacks for DoxygenCallbacks { } } -const LIBS: &[&'static str] = &[ - #[cfg(feature = "nix-util-c")] - "nix-util-c", - #[cfg(feature = "nix-store-c")] - "nix-store-c", - #[cfg(feature = "nix-expr-c")] - "nix-expr-c", - #[cfg(feature = "nix-fetchers-c")] - "nix-fetchers-c", - #[cfg(feature = "nix-flake-c")] - "nix-flake-c", - #[cfg(feature = "nix-main-c")] - "nix-main-c", -]; - fn main() { - // Invalidate the built crate if the binding headers change - // println!("cargo::rerun-if-changed=include"); + // Invalidate the built crate whenever the wrapper changes + println!("cargo::rerun-if-changed=include/nix-util.h"); + println!("cargo::rerun-if-changed=include/nix-store.h"); + println!("cargo::rerun-if-changed=include/nix-expr.h"); + println!("cargo::rerun-if-changed=include/nix-fetchers.h"); + println!("cargo::rerun-if-changed=include/nix-flake.h"); + println!("cargo::rerun-if-changed=include/nix-main.h"); - let lib_args: Vec = LIBS + let libs = [ + #[cfg(feature = "nix-util-c")] + "nix-util-c", + #[cfg(feature = "nix-store-c")] + "nix-store-c", + #[cfg(feature = "nix-expr-c")] + "nix-expr-c", + #[cfg(feature = "nix-fetchers-c")] + "nix-fetchers-c", + #[cfg(feature = "nix-flake-c")] + "nix-flake-c", + #[cfg(feature = "nix-main-c")] + "nix-main-c", + ]; + + let lib_args: Vec = libs .iter() .map(|&name| { let lib = pkg_config::probe_library(name) @@ -52,35 +57,52 @@ fn main() { .map(|p| format!("-I{}", p.display())) }) .flatten() - .chain(vec!["-Wall".to_owned(), "-xc++".to_owned()]) .collect(); let mut builder = bindgen::Builder::default() - // .clang_arg("") // libnix uses c++23 .clang_args(lib_args) + // Invalidate the built crate when an included header file changes .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) // Add `doxygen_bindgen` callbacks .parse_callbacks(Box::new(DoxygenCallbacks)) // Format generated bindings with rustfmt .formatter(bindgen::Formatter::Rustfmt) - .rustfmt_configuration_file(std::fs::canonicalize("rustfmt.toml").ok()); + .rustfmt_configuration_file(std::fs::canonicalize(".rustfmt.toml").ok()); - // Register the input headers we would like to generate bindings for - builder = LIBS - .iter() - .map(|lib| { - let path = format!("include/{}.h", lib.strip_suffix("-c").unwrap()); - assert!(fs::exists(&path).unwrap()); - // Invalidate the built crate if the binding headers change - // println!("cargo::rerun-if-changed={path}"); - path - }) - .fold(builder, |builder, path| builder.header(path)); + // The input headers we would like to generate bindings for + #[cfg(feature = "nix-util-c")] + { + builder = builder.header("include/nix-util.h") + } + #[cfg(feature = "nix-store-c")] + { + builder = builder.header("include/nix-store.h") + } + #[cfg(feature = "nix-expr-c")] + { + builder = builder.header("include/nix-expr.h") + } + #[cfg(feature = "nix-fetchers-c")] + { + builder = builder.header("include/nix-fetchers.h") + } + #[cfg(feature = "nix-flake-c")] + { + builder = builder.header("include/nix-flake.h") + } + #[cfg(feature = "nix-main-c")] + { + builder = builder.header("include/nix-main.h") + } + + let bindings = builder + // Finish the builder and generate the bindings + .generate() + // Unwrap the Result and panic on failure + .expect("Unable to generate bindings"); // Write the bindings to the $OUT_DIR/bindings.rs file let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - - let bindings = builder.generate().expect("Unable to generate bindings"); bindings .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); diff --git a/nixide/src/expr/eval_state.rs b/nixide/src/expr/eval_state.rs index 10644fb..c491642 100644 --- a/nixide/src/expr/eval_state.rs +++ b/nixide/src/expr/eval_state.rs @@ -1,8 +1,7 @@ -use std::cell::RefCell; +use std::ffi::{CString, c_void}; use std::ptr::NonNull; -use std::rc::Rc; -use crate::stdext::AsCPtr as _; +use crate::errors::new_nixide_error; use super::Value; use crate::errors::ErrorContext; @@ -16,9 +15,9 @@ use crate::{NixideResult, Store}; /// This provides the main interface for evaluating Nix expressions /// and creating values. pub struct EvalState { - inner: Rc>>, + inner: NonNull, - store: Rc>, + store: Store, } // impl Clone for EvalState { @@ -40,37 +39,31 @@ pub struct EvalState { impl AsInnerPtr for EvalState { #[inline] unsafe fn as_ptr(&self) -> *mut sys::EvalState { - self.inner.borrow().as_ptr() + self.inner.as_ptr() } #[inline] unsafe fn as_ref(&self) -> &sys::EvalState { - unsafe { self.inner.borrow().as_ref() } + unsafe { self.inner.as_ref() } } #[inline] unsafe fn as_mut(&mut self) -> &mut sys::EvalState { - unsafe { self.inner.borrow_mut().as_mut() } + unsafe { self.inner.as_mut() } } } impl EvalState { /// Construct a new EvalState directly from its attributes /// - pub(super) fn from(inner: NonNull, store: Rc>) -> Self { + pub(super) fn new(inner: NonNull, store: &Store) -> Self { Self { - inner: Rc::new(RefCell::new(inner)), - store, + inner, + store: store.clone(), } } - #[inline] - pub fn inner_ref(&self) -> &Rc>> { - &self.inner - } - - #[inline] - pub fn store_ref(&self) -> &Rc> { + pub fn store_ref(&self) -> &Store { &self.store } @@ -84,10 +77,9 @@ impl EvalState { /// # Errors /// /// Returns an error if evaluation fails. - /// pub fn interpret(&self, expr: &str, path: &str) -> NixideResult { - let expr = expr.as_c_ptr()?; - let path = path.as_c_ptr()?; + let expr_c = CString::new(expr).or(Err(new_nixide_error!(StringNulByte)))?; + let path_c = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?; // Allocate value for result // XXX: TODO: create a method for this (``) @@ -98,10 +90,16 @@ impl EvalState { // Evaluate expression wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_expr_eval_from_string(ctx.as_ptr(), self.as_ptr(), expr, path, value.as_ptr()); + sys::nix_expr_eval_from_string( + ctx.as_ptr(), + self.as_ptr(), + expr_c.as_ptr(), + path_c.as_ptr(), + value.as_ptr(), + ); value }) - .map(|ptr| Value::from((ptr, self.inner_ref().clone()))) + .map(|ptr| Value::from((ptr, self))) } } @@ -112,3 +110,7 @@ impl Drop for EvalState { } } } + +// SAFETY: EvalState can be shared between threads +unsafe impl Send for EvalState {} +unsafe impl Sync for EvalState {} diff --git a/nixide/src/expr/eval_state_builder.rs b/nixide/src/expr/eval_state_builder.rs index 2ae0056..ee3faeb 100644 --- a/nixide/src/expr/eval_state_builder.rs +++ b/nixide/src/expr/eval_state_builder.rs @@ -1,7 +1,5 @@ -use std::cell::RefCell; -use std::ffi::{CString, c_char}; +use std::ffi::{CString, c_char, c_void}; use std::ptr::{self, NonNull}; -use std::rc::Rc; use super::EvalState; #[cfg(feature = "flakes")] @@ -18,24 +16,40 @@ use crate::util::{panic_issue_call_failed, wrap}; /// the evaluation state. /// pub struct EvalStateBuilder { - inner: Rc>>, - store: Rc>, + inner: NonNull, + store: Store, } +// impl Clone for EvalStateBuilder { +// fn clone(&self) -> Self { +// let inner = self.inner.clone(); +// +// wrap::nix_fn!(|ctx: &ErrorContext| unsafe { +// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void); +// }) +// .unwrap(); +// +// Self { +// inner, +// store: self.store.clone(), +// } +// } +// } + impl AsInnerPtr for EvalStateBuilder { #[inline] unsafe fn as_ptr(&self) -> *mut sys::nix_eval_state_builder { - self.inner.borrow().as_ptr() + self.inner.as_ptr() } #[inline] unsafe fn as_ref(&self) -> &sys::nix_eval_state_builder { - unsafe { self.inner.borrow().as_ref() } + unsafe { self.inner.as_ref() } } #[inline] unsafe fn as_mut(&mut self) -> &mut sys::nix_eval_state_builder { - unsafe { self.inner.borrow_mut().as_mut() } + unsafe { self.inner.as_mut() } } } @@ -50,14 +64,14 @@ impl EvalStateBuilder { /// /// Returns an error if the builder cannot be created. /// - pub fn new(store: Rc>) -> NixideResult { + pub fn new(store: &Store) -> NixideResult { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_eval_state_builder_new(ctx.as_ptr(), store.borrow().as_ptr()) + sys::nix_eval_state_builder_new(ctx.as_ptr(), store.as_ptr()) })?; Ok(EvalStateBuilder { - inner: Rc::new(RefCell::new(inner)), - store, + inner, + store: store.clone(), }) } @@ -73,7 +87,7 @@ impl EvalStateBuilder { sys::nix_eval_state_build(ctx.as_ptr(), self.as_ptr()) })?; - Ok(EvalState::from(inner, self.store.clone())) + Ok(EvalState::new(inner, &self.store)) } // XXX: TODO: use `flakes()` instead diff --git a/nixide/src/expr/realised_string.rs b/nixide/src/expr/realised_string.rs index 0d41b6f..5d5e08f 100644 --- a/nixide/src/expr/realised_string.rs +++ b/nixide/src/expr/realised_string.rs @@ -1,15 +1,15 @@ use std::cell::RefCell; -use std::ffi::c_char; +use std::ffi::{c_char, c_void}; use std::ptr::NonNull; use crate::errors::ErrorContext; use crate::expr::values::NixString; use crate::stdext::CCharPtrExt; +use crate::sys; use crate::util::LazyArray; use crate::util::wrappers::AsInnerPtr; use crate::util::{panic_issue_call_failed, wrap}; use crate::{EvalState, NixideResult, StorePath}; -use crate::{Store, sys}; pub struct RealisedString<'a> { inner: RefCell>, @@ -17,6 +17,23 @@ pub struct RealisedString<'a> { pub children: LazyArray StorePath + 'a>>, } +// impl<'a> Clone for RealisedString<'a> { +// fn clone(&self) -> Self { +// let inner = self.inner.clone(); + +// wrap::nix_fn!(|ctx: &ErrorContext| unsafe { +// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void); +// }) +// .unwrap(); + +// Self { +// inner, +// path: self.path.clone(), +// children: self.children, +// } +// } +// } + impl<'a> AsInnerPtr for RealisedString<'a> { #[inline] unsafe fn as_ptr(&self) -> *mut sys::nix_realised_string { @@ -46,7 +63,7 @@ impl<'a> RealisedString<'a> { /// Realise a string context. /// /// This will - /// - realise the store paths referenced by the string's content, and + /// - realise the store paths referenced by the string's context, and /// - perform the replacement of placeholders. /// - create temporary garbage collection roots for the store paths, for /// the lifetime of the current process. @@ -60,6 +77,9 @@ impl<'a> RealisedString<'a> { /// You should set this to true when this call is part of a primop. /// You should set this to false when building for your application's purpose. /// + /// # Returns + /// + /// NULL if failed, or a new nix_realised_string, which must be freed with nix_realised_string_free pub fn new(value: &NixString, state: &'a EvalState) -> NixideResult> { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { sys::nix_string_realise( @@ -69,20 +89,21 @@ impl<'a> RealisedString<'a> { false, // don't copy more ) })?; + let cell = RefCell::new(inner); let size = unsafe { sys::nix_realised_string_get_store_path_count(inner.as_ptr()) }; Ok(Self { - inner: RefCell::new(inner), - path: Self::parse_path(inner.as_ptr(), &state.store_ref().borrow()), + inner: cell, + path: Self::parse_path(inner.as_ptr(), state), children: LazyArray::new( size, - Box::new(|_| StorePath::fake_path(&state.store_ref().borrow()).unwrap()), + Box::new(|_| StorePath::fake_path(state.store_ref()).unwrap()), ), }) } - fn parse_path(realised_string: *mut sys::nix_realised_string, store: &Store) -> StorePath { + fn parse_path(realised_string: *mut sys::nix_realised_string, state: &EvalState) -> StorePath { let buffer_ptr = unsafe { sys::nix_realised_string_get_buffer_start(realised_string) }; let buffer_size = unsafe { sys::nix_realised_string_get_buffer_size(realised_string) }; @@ -94,7 +115,7 @@ impl<'a> RealisedString<'a> { err ) }); - StorePath::parse(store, &path_str).unwrap_or_else(|err| { + StorePath::parse(state.store_ref(), &path_str).unwrap_or_else(|err| { panic_issue_call_failed!( "`sys::nix_realised_string_get_buffer_(start|size)` invalid store path ({})", err diff --git a/nixide/src/expr/tests.rs b/nixide/src/expr/tests.rs index e9342d0..5233ea2 100644 --- a/nixide/src/expr/tests.rs +++ b/nixide/src/expr/tests.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use serial_test::serial; use super::{EvalStateBuilder, Value}; @@ -6,18 +8,19 @@ use crate::Store; #[test] #[serial] fn test_eval_state_builder() { - let store = Store::default().expect("Failed to open store"); - let _state = EvalStateBuilder::new(store.clone()) + let store = Rc::new(Store::default().expect("Failed to open store")); + let _state = EvalStateBuilder::new(&store) .expect("Failed to create builder") .build() .expect("Failed to build state"); + // State should be dropped automatically } #[test] #[serial] fn test_simple_evaluation() { - let store = Store::default().expect("Failed to open store"); - let state = EvalStateBuilder::new(store.clone()) + let store = Rc::new(Store::default().expect("Failed to open store")); + let state = EvalStateBuilder::new(&store) .expect("Failed to create builder") .build() .expect("Failed to build state"); @@ -38,7 +41,7 @@ fn test_simple_evaluation() { #[serial] fn test_value_types() { let store = Store::default().expect("Failed to open store"); - let state = EvalStateBuilder::new(store.clone()) + let state = EvalStateBuilder::new(&store) .expect("Failed to create builder") .build() .expect("Failed to build state"); @@ -81,7 +84,7 @@ fn test_value_types() { #[serial] fn test_value_formatting() { let store = Store::default().expect("Failed to open store"); - let state = EvalStateBuilder::new(store.clone()) + let state = EvalStateBuilder::new(&store) .expect("Failed to create builder") .build() .expect("Failed to build state"); diff --git a/nixide/src/expr/values/attrs.rs b/nixide/src/expr/values/attrs.rs index 0213e54..9f8f8e4 100644 --- a/nixide/src/expr/values/attrs.rs +++ b/nixide/src/expr/values/attrs.rs @@ -1,19 +1,17 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::{self, NonNull}; -use std::rc::Rc; use super::{NixThunk, NixValue, Value}; -use crate::NixError; use crate::errors::{ErrorContext, NixideError}; use crate::stdext::{AsCPtr, CCharPtrExt}; use crate::sys; use crate::util::wrappers::AsInnerPtr; use crate::util::{panic_issue_call_failed, wrap}; +use crate::{EvalState, NixError}; pub struct NixAttrs { inner: NonNull, - state: Rc>>, + state: EvalState, len: u32, } @@ -78,13 +76,17 @@ impl NixValue for NixAttrs { sys::ValueType_NIX_TYPE_ATTRS } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: &EvalState) -> Self { let len = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_attrs_size(ctx.as_ptr(), inner.as_ptr()) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Self { inner, state, len } + Self { + inner, + state: state.clone(), + len, + } } } @@ -105,7 +107,7 @@ impl NixAttrs { sys::nix_get_attr_byidx( ctx.as_ptr(), self.as_ptr(), - self.state.borrow().as_ptr(), + self.state.as_ptr(), index, name_ptr, ) @@ -116,7 +118,7 @@ impl NixAttrs { .to_utf8_string() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - let value = Value::from((inner, self.state.clone())); + let value = Value::from((inner, &self.state)); Some((name, value)) } @@ -132,7 +134,7 @@ impl NixAttrs { sys::nix_get_attr_byidx_lazy( ctx.as_ptr(), self.as_ptr(), - self.state.borrow().as_ptr(), + self.state.as_ptr(), index, name_ptr, ) @@ -143,7 +145,7 @@ impl NixAttrs { .to_utf8_string() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - let value = ::from(inner, self.state.clone()); + let value = ::from(inner, &self.state); Some((name, value)) } @@ -154,12 +156,7 @@ impl NixAttrs { } let name_ptr = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_get_attr_name_byidx( - ctx.as_ptr(), - self.as_ptr(), - self.state.borrow().as_ptr(), - index, - ) + sys::nix_get_attr_name_byidx(ctx.as_ptr(), self.as_ptr(), self.state.as_ptr(), index) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); @@ -178,7 +175,7 @@ impl NixAttrs { sys::nix_get_attr_byname( ctx.as_ptr(), self.as_ptr(), - self.state.borrow().as_ptr(), + self.state.as_ptr(), name.as_ref() .into_c_ptr() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)), @@ -186,7 +183,7 @@ impl NixAttrs { }); match result { - Ok(inner) => Some(Value::from((inner, self.state.clone()))), + Ok(inner) => Some(Value::from((inner, &self.state))), Err(NixideError::NixError { err: NixError::KeyNotFound(_), @@ -204,7 +201,7 @@ impl NixAttrs { sys::nix_get_attr_byname_lazy( ctx.as_ptr(), self.as_ptr(), - self.state.borrow().as_ptr(), + self.state.as_ptr(), name.as_ref() .into_c_ptr() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)), @@ -212,7 +209,7 @@ impl NixAttrs { }); match result { - Ok(inner) => Some(::from(inner, self.state.clone())), + Ok(inner) => Some(::from(inner, &self.state)), Err(NixideError::NixError { err: NixError::KeyNotFound(_), diff --git a/nixide/src/expr/values/bool.rs b/nixide/src/expr/values/bool.rs index 54fcade..dd04031 100644 --- a/nixide/src/expr/values/bool.rs +++ b/nixide/src/expr/values/bool.rs @@ -1,18 +1,16 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::NixValue; use crate::errors::ErrorContext; -use crate::sys; use crate::util::panic_issue_call_failed; use crate::util::wrap; use crate::util::wrappers::AsInnerPtr; +use crate::{EvalState, sys}; pub struct NixBool { inner: NonNull, - state: Rc>>, + state: EvalState, value: bool, } @@ -77,7 +75,7 @@ impl NixValue for NixBool { sys::ValueType_NIX_TYPE_BOOL } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: &EvalState) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_bool(ctx.as_ptr(), inner.as_ptr()) }) @@ -87,7 +85,7 @@ impl NixValue for NixBool { Self { inner, - state, + state: state.clone(), value, } } diff --git a/nixide/src/expr/values/float.rs b/nixide/src/expr/values/float.rs index 3b0be68..9538b45 100644 --- a/nixide/src/expr/values/float.rs +++ b/nixide/src/expr/values/float.rs @@ -1,9 +1,8 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::NixValue; +use crate::EvalState; use crate::errors::ErrorContext; use crate::sys; use crate::util::wrappers::AsInnerPtr; @@ -11,7 +10,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixFloat { inner: NonNull, - state: Rc>>, + state: EvalState, value: f64, } @@ -76,7 +75,7 @@ impl NixValue for NixFloat { sys::ValueType_NIX_TYPE_FLOAT } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: &EvalState) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_float(ctx.as_ptr(), inner.as_ptr()) }) @@ -86,7 +85,7 @@ impl NixValue for NixFloat { Self { inner, - state, + state: state.clone(), value, } } diff --git a/nixide/src/expr/values/function.rs b/nixide/src/expr/values/function.rs index 5ed9a18..83d7d2a 100644 --- a/nixide/src/expr/values/function.rs +++ b/nixide/src/expr/values/function.rs @@ -1,18 +1,16 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::{NixValue, Value}; use crate::errors::ErrorContext; use crate::stdext::SliceExt; -use crate::sys; use crate::util::wrappers::AsInnerPtr; use crate::util::{panic_issue_call_failed, wrap}; +use crate::{EvalState, sys}; pub struct NixFunction { inner: NonNull, - state: Rc>>, + state: EvalState, } impl Clone for NixFunction { @@ -75,8 +73,11 @@ impl NixValue for NixFunction { sys::ValueType_NIX_TYPE_FUNCTION } - fn from(inner: NonNull, state: Rc>>) -> Self { - Self { inner, state } + fn from(inner: NonNull, state: &EvalState) -> Self { + Self { + inner, + state: state.clone(), + } } } @@ -86,14 +87,14 @@ impl NixFunction { T: NixValue, { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().as_ptr()) + sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr()) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_value_call( ctx.as_ptr(), - self.state.borrow().as_ptr(), + self.state.as_ptr(), self.as_ptr(), arg.as_ptr(), inner.as_ptr(), @@ -101,7 +102,7 @@ impl NixFunction { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((inner, self.state.clone())) + Value::from((inner, &self.state)) } pub fn call_many(&self, args: &[&T]) -> Value @@ -109,14 +110,14 @@ impl NixFunction { T: NixValue, { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().as_ptr()) + sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr()) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_value_call_multi( ctx.as_ptr(), - self.state.borrow().as_ptr(), + self.state.as_ptr(), self.as_ptr(), args.len(), args.into_c_array(), @@ -125,7 +126,7 @@ impl NixFunction { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((inner, self.state.clone())) + Value::from((inner, &self.state)) } } diff --git a/nixide/src/expr/values/int.rs b/nixide/src/expr/values/int.rs index 815edef..86e5e94 100644 --- a/nixide/src/expr/values/int.rs +++ b/nixide/src/expr/values/int.rs @@ -1,9 +1,8 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::NixValue; +use crate::EvalState; use crate::errors::ErrorContext; use crate::sys; use crate::util::wrappers::AsInnerPtr; @@ -11,7 +10,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixInt { inner: NonNull, - state: Rc>>, + state: EvalState, value: i64, } @@ -76,7 +75,7 @@ impl NixValue for NixInt { sys::ValueType_NIX_TYPE_INT } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: &EvalState) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_int(ctx.as_ptr(), inner.as_ptr()) }) @@ -84,7 +83,7 @@ impl NixValue for NixInt { Self { inner, - state, + state: state.clone(), value, } } diff --git a/nixide/src/expr/values/list.rs b/nixide/src/expr/values/list.rs index 7172f8b..4c0f354 100644 --- a/nixide/src/expr/values/list.rs +++ b/nixide/src/expr/values/list.rs @@ -1,9 +1,8 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::{NixThunk, NixValue, Value}; +use crate::EvalState; use crate::errors::ErrorContext; use crate::sys; use crate::util::wrappers::AsInnerPtr; @@ -11,7 +10,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixList { inner: NonNull, - state: Rc>>, + state: EvalState, } impl Clone for NixList { @@ -74,8 +73,11 @@ impl NixValue for NixList { sys::ValueType_NIX_TYPE_LIST } - fn from(inner: NonNull, state: Rc>>) -> Self { - Self { inner, state } + fn from(inner: NonNull, state: &EvalState) -> Self { + Self { + inner, + state: state.clone(), + } } } @@ -114,29 +116,19 @@ impl NixList { pub fn get(&self, index: u32) -> Value { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_get_list_byidx( - ctx.as_ptr(), - self.as_ptr(), - self.state.borrow().as_ptr(), - index, - ) + sys::nix_get_list_byidx(ctx.as_ptr(), self.as_ptr(), self.state.as_ptr(), index) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((inner, self.state.clone())) + Value::from((inner, &self.state)) } pub fn get_lazy(&self, index: u32) -> NixThunk { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_get_list_byidx_lazy( - ctx.as_ptr(), - self.as_ptr(), - self.state.borrow().as_ptr(), - index, - ) + sys::nix_get_list_byidx_lazy(ctx.as_ptr(), self.as_ptr(), self.state.as_ptr(), index) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - ::from(inner, self.state.clone()) + ::from(inner, &self.state) } } diff --git a/nixide/src/expr/values/mod.rs b/nixide/src/expr/values/mod.rs index a06edde..f6f6b80 100644 --- a/nixide/src/expr/values/mod.rs +++ b/nixide/src/expr/values/mod.rs @@ -23,11 +23,10 @@ pub use path::NixPath; pub use string::NixString; pub use thunk::NixThunk; -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; +use crate::EvalState; use crate::errors::ErrorContext; use crate::sys; use crate::sys::{ @@ -44,7 +43,7 @@ pub trait NixValue: Clone + Drop + Display + Debug + AsInnerPtr fn type_id(&self) -> sys::ValueType; /// TODO - fn from(inner: NonNull, state: Rc>>) -> Self; + fn from(inner: NonNull, state: &EvalState) -> Self; } /// A Nix value @@ -110,22 +109,12 @@ pub enum Value { // Failed(NixFailed), } -impl - From<( - NonNull, - Rc>>, - )> for Value -{ - fn from( - value: ( - NonNull, - Rc>>, - ), - ) -> Self { +impl From<(NonNull, &EvalState)> for Value { + fn from(value: (NonNull, &EvalState)) -> Self { let (inner, state) = value; wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_value_force(ctx.as_ptr(), state.borrow().as_ptr(), inner.as_ptr()) + sys::nix_value_force(ctx.as_ptr(), state.as_ptr(), inner.as_ptr()) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); diff --git a/nixide/src/expr/values/null.rs b/nixide/src/expr/values/null.rs index 46bfe15..fd20445 100644 --- a/nixide/src/expr/values/null.rs +++ b/nixide/src/expr/values/null.rs @@ -1,9 +1,8 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::NixValue; +use crate::EvalState; use crate::errors::ErrorContext; use crate::sys; use crate::util::wrap; @@ -11,7 +10,7 @@ use crate::util::wrappers::AsInnerPtr; pub struct NixNull { inner: NonNull, - state: Rc>>, + state: EvalState, } impl Clone for NixNull { @@ -74,7 +73,10 @@ impl NixValue for NixNull { sys::ValueType_NIX_TYPE_NULL } - fn from(inner: NonNull, state: Rc>>) -> Self { - Self { inner, state } + fn from(inner: NonNull, state: &EvalState) -> Self { + Self { + inner, + state: state.clone(), + } } } diff --git a/nixide/src/expr/values/path.rs b/nixide/src/expr/values/path.rs index f9a49a0..6d51fd6 100644 --- a/nixide/src/expr/values/path.rs +++ b/nixide/src/expr/values/path.rs @@ -1,20 +1,18 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::path::PathBuf; use std::ptr::NonNull; -use std::rc::Rc; use super::NixValue; use crate::errors::ErrorContext; use crate::stdext::CCharPtrExt; -use crate::sys; use crate::util::panic_issue_call_failed; use crate::util::wrap; use crate::util::wrappers::AsInnerPtr; +use crate::{EvalState, sys}; pub struct NixPath { inner: NonNull, - state: Rc>>, + state: EvalState, value: PathBuf, } @@ -79,7 +77,7 @@ impl NixValue for NixPath { sys::ValueType_NIX_TYPE_PATH } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: &EvalState) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_path_string(ctx.as_ptr(), inner.as_ptr()) }) @@ -89,7 +87,7 @@ impl NixValue for NixPath { Self { inner, - state, + state: state.clone(), value, } } diff --git a/nixide/src/expr/values/string.rs b/nixide/src/expr/values/string.rs index d2582de..765d763 100644 --- a/nixide/src/expr/values/string.rs +++ b/nixide/src/expr/values/string.rs @@ -1,19 +1,16 @@ -use std::cell::RefCell; -use std::ffi::c_void; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::NixValue; use crate::errors::ErrorContext; -use crate::sys; use crate::util::panic_issue_call_failed; use crate::util::wrap; use crate::util::wrappers::AsInnerPtr; +use crate::{EvalState, sys}; pub struct NixString { inner: NonNull, - state: Rc>>, + state: EvalState, value: String, } @@ -78,7 +75,7 @@ impl NixValue for NixString { sys::ValueType_NIX_TYPE_STRING } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: &EvalState) -> Self { let value = wrap::nix_string_callback!( |callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { sys::nix_get_string( @@ -93,7 +90,7 @@ impl NixValue for NixString { Self { inner, - state, + state: state.clone(), value, } } diff --git a/nixide/src/expr/values/thunk.rs b/nixide/src/expr/values/thunk.rs index 294745e..b6439ce 100644 --- a/nixide/src/expr/values/thunk.rs +++ b/nixide/src/expr/values/thunk.rs @@ -1,9 +1,8 @@ -use std::cell::RefCell; use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; -use std::rc::Rc; use super::{NixValue, Value}; +use crate::EvalState; use crate::errors::ErrorContext; use crate::sys; use crate::util::wrappers::AsInnerPtr; @@ -11,7 +10,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixThunk { inner: NonNull, - state: Rc>>, + state: EvalState, } impl Clone for NixThunk { @@ -74,22 +73,21 @@ impl NixValue for NixThunk { sys::ValueType_NIX_TYPE_THUNK } - fn from(inner: NonNull, state: Rc>>) -> Self { - Self { inner, state } + fn from(inner: NonNull, state: &EvalState) -> Self { + Self { + inner, + state: state.clone(), + } } } impl NixThunk { pub fn eval(self) -> Value { wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_value_force( - ctx.as_ptr(), - self.state.borrow().as_ptr(), - self.inner.as_ptr(), - ) + sys::nix_value_force(ctx.as_ptr(), self.state.as_ptr(), self.inner.as_ptr()) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((self.inner, self.state.clone())) + Value::from((self.inner, &self.state)) } } diff --git a/nixide/src/flake/fetchers_settings.rs b/nixide/src/flake/fetchers_settings.rs index cf15df2..1f24d04 100644 --- a/nixide/src/flake/fetchers_settings.rs +++ b/nixide/src/flake/fetchers_settings.rs @@ -1,3 +1,4 @@ +use std::ffi::c_void; use std::ptr::NonNull; use crate::NixideResult; diff --git a/nixide/src/flake/flake_settings.rs b/nixide/src/flake/flake_settings.rs index 9d11358..295115b 100644 --- a/nixide/src/flake/flake_settings.rs +++ b/nixide/src/flake/flake_settings.rs @@ -1,3 +1,4 @@ +use std::ffi::c_void; use std::ptr::NonNull; use crate::NixideResult; @@ -19,6 +20,19 @@ impl Drop for FlakeSettings { } } +// impl Clone for FlakeSettings { +// fn clone(&self) -> Self { +// let inner = self.inner.clone(); +// +// wrap::nix_fn!(|ctx: &ErrorContext| unsafe { +// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void); +// }) +// .unwrap(); +// +// Self { inner } +// } +// } + impl AsInnerPtr for FlakeSettings { #[inline] unsafe fn as_ptr(&self) -> *mut sys::nix_flake_settings { diff --git a/nixide/src/flake/locked_flake.rs b/nixide/src/flake/locked_flake.rs index 4f0237c..a2ae9af 100644 --- a/nixide/src/flake/locked_flake.rs +++ b/nixide/src/flake/locked_flake.rs @@ -1,5 +1,6 @@ // XXX: TODO: find a way to read directly from FlakeSettings and FetchersSettings (the C++ classes) +use std::ffi::c_void; use std::ptr::NonNull; use super::{FetchersSettings, FlakeLockFlags, FlakeReference, FlakeSettings}; @@ -129,8 +130,8 @@ mod tests { fn flake_settings_getflake_exists() { init(); - let store_ref = Store::default().expect("Failed to open store connection"); - let state = EvalStateBuilder::new(store_ref.clone()) + let store = Store::default().expect("Failed to open store connection"); + let state = EvalStateBuilder::new(&store) .unwrap() .flakes() .unwrap() @@ -164,10 +165,10 @@ mod tests { ) .unwrap(); - let store_ref = Store::default().unwrap(); + let store = Store::default().unwrap(); let flake_settings = FlakeSettings::new().unwrap(); - let mut eval_state = EvalStateBuilder::new(store_ref.clone()) + let mut eval_state = EvalStateBuilder::new(&store) .unwrap() .set_flake_settings(&flake_settings) .unwrap() @@ -213,10 +214,10 @@ mod tests { fn flake_lock_load_flake_with_flags() { init(); - let store_ref = Store::default().unwrap(); + let store = Store::default().unwrap(); let fetchers_settings = FetchersSettings::new().unwrap(); let flake_settings = FlakeSettings::new().unwrap(); - let mut eval_state = EvalStateBuilder::new(store_ref.clone()) + let mut eval_state = EvalStateBuilder::new(&store) .unwrap() .set_flake_settings(&flake_settings) .unwrap() diff --git a/nixide/src/store/mod.rs b/nixide/src/store/mod.rs index f40a395..35c04e8 100644 --- a/nixide/src/store/mod.rs +++ b/nixide/src/store/mod.rs @@ -7,11 +7,9 @@ mod tests; mod path; pub use path::*; -use std::cell::RefCell; use std::ffi::{c_char, c_void}; use std::path::PathBuf; use std::ptr::{NonNull, null, null_mut}; -use std::rc::Rc; use crate::NixideResult; use crate::errors::ErrorContext; @@ -70,24 +68,24 @@ impl Store { /// /// Returns an error if the store cannot be opened. /// - pub fn open(uri: &str) -> NixideResult>> { + pub fn open(uri: &str) -> NixideResult { Self::open_ptr(uri.as_c_ptr()?) } /// Opens a connection to the default Nix store. /// - pub fn default() -> NixideResult>> { + pub fn default() -> NixideResult { Self::open_ptr(null()) } #[inline] - fn open_ptr(uri_ptr: *const c_char) -> NixideResult>> { + fn open_ptr(uri_ptr: *const c_char) -> NixideResult { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { // XXX: TODO: allow args to be parsed instead of just `null_mut` sys::nix_store_open(ctx.as_ptr(), uri_ptr, null_mut()) })?; - Ok(Rc::new(RefCell::new(Store { inner }))) + Ok(Store { inner }) } /// Realize a store path. diff --git a/nixide/src/store/tests.rs b/nixide/src/store/tests.rs index 1a9c3ac..5943077 100644 --- a/nixide/src/store/tests.rs +++ b/nixide/src/store/tests.rs @@ -1,7 +1,10 @@ use serial_test::serial; use super::{Store, StorePath}; +use crate::errors::ErrorContext; use crate::init::LIBNIX_INIT_STATUS; +use crate::sys; +use crate::util::wrappers::AsInnerPtr as _; #[test] #[serial] @@ -19,7 +22,7 @@ fn test_store_path_parse() { let store = Store::default().expect("Failed to open store"); // Try parsing a well-formed store path - let result = StorePath::fake_path(&store.borrow()); + let result = StorePath::fake_path(&store); result.expect("idk hopefully this fails"); } @@ -31,8 +34,7 @@ fn test_store_path_clone() { let store = Store::default().expect("Failed to open store"); // Try to get a valid store path by parsing - let path = - StorePath::fake_path(&store.borrow()).expect("Failed to create `StorePath::fake_path`"); + let path = StorePath::fake_path(&store).expect("Failed to create `StorePath::fake_path`"); let cloned = path.clone(); // Assert that the cloned path has the same name as the original