From c5c3f6c8d462516068c3887735672aa7732d6d06 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Mon, 30 Mar 2026 15:05:20 +1000 Subject: [PATCH 1/3] internally pass EvalState via Rc>> --- nixide/src/expr/eval_state.rs | 46 +++++++++++++-------------- nixide/src/expr/eval_state_builder.rs | 24 +++++++------- nixide/src/expr/realised_string.rs | 37 +++++---------------- nixide/src/expr/tests.rs | 15 ++++----- nixide/src/expr/values/attrs.rs | 21 ++++++++---- nixide/src/expr/values/bool.rs | 6 ++-- nixide/src/expr/values/float.rs | 6 ++-- nixide/src/expr/values/function.rs | 14 ++++---- nixide/src/expr/values/int.rs | 6 ++-- nixide/src/expr/values/list.rs | 20 +++++++++--- nixide/src/expr/values/null.rs | 6 ++-- nixide/src/expr/values/path.rs | 6 ++-- nixide/src/expr/values/string.rs | 7 ++-- nixide/src/expr/values/thunk.rs | 12 +++++-- nixide/src/flake/fetchers_settings.rs | 1 - nixide/src/store/mod.rs | 10 +++--- 16 files changed, 127 insertions(+), 110 deletions(-) diff --git a/nixide/src/expr/eval_state.rs b/nixide/src/expr/eval_state.rs index c491642..0103416 100644 --- a/nixide/src/expr/eval_state.rs +++ b/nixide/src/expr/eval_state.rs @@ -1,7 +1,8 @@ -use std::ffi::{CString, c_void}; +use std::cell::RefCell; use std::ptr::NonNull; +use std::rc::Rc; -use crate::errors::new_nixide_error; +use crate::stdext::AsCPtr as _; use super::Value; use crate::errors::ErrorContext; @@ -15,9 +16,9 @@ use crate::{NixideResult, Store}; /// This provides the main interface for evaluating Nix expressions /// and creating values. pub struct EvalState { - inner: NonNull, + inner: Rc>>, - store: Store, + store: Rc>, } // impl Clone for EvalState { @@ -39,31 +40,37 @@ pub struct EvalState { impl AsInnerPtr for EvalState { #[inline] unsafe fn as_ptr(&self) -> *mut sys::EvalState { - self.inner.as_ptr() + self.inner.borrow().as_ptr() } #[inline] unsafe fn as_ref(&self) -> &sys::EvalState { - unsafe { self.inner.as_ref() } + unsafe { self.inner.borrow().as_ref() } } #[inline] unsafe fn as_mut(&mut self) -> &mut sys::EvalState { - unsafe { self.inner.as_mut() } + unsafe { self.inner.borrow_mut().as_mut() } } } impl EvalState { /// Construct a new EvalState directly from its attributes /// - pub(super) fn new(inner: NonNull, store: &Store) -> Self { + pub(super) fn from(inner: NonNull, store: Rc>) -> Self { Self { - inner, - store: store.clone(), + inner: Rc::new(RefCell::new(inner)), + store, } } - pub fn store_ref(&self) -> &Store { + #[inline] + pub fn inner_ref(&self) -> &Rc>> { + &self.inner + } + + #[inline] + pub fn store_ref(&self) -> &Rc> { &self.store } @@ -77,9 +84,10 @@ impl EvalState { /// # Errors /// /// Returns an error if evaluation fails. + /// pub fn interpret(&self, expr: &str, path: &str) -> NixideResult { - let expr_c = CString::new(expr).or(Err(new_nixide_error!(StringNulByte)))?; - let path_c = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?; + let expr = expr.as_c_ptr()?; + let path = path.as_c_ptr()?; // Allocate value for result // XXX: TODO: create a method for this (``) @@ -90,13 +98,7 @@ impl EvalState { // Evaluate expression wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_expr_eval_from_string( - ctx.as_ptr(), - self.as_ptr(), - expr_c.as_ptr(), - path_c.as_ptr(), - value.as_ptr(), - ); + sys::nix_expr_eval_from_string(ctx.as_ptr(), self.as_ptr(), expr, path, value.as_ptr()); value }) .map(|ptr| Value::from((ptr, self))) @@ -110,7 +112,3 @@ 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 ee3faeb..af4fd7d 100644 --- a/nixide/src/expr/eval_state_builder.rs +++ b/nixide/src/expr/eval_state_builder.rs @@ -1,5 +1,7 @@ -use std::ffi::{CString, c_char, c_void}; +use std::cell::RefCell; +use std::ffi::{CString, c_char}; use std::ptr::{self, NonNull}; +use std::rc::Rc; use super::EvalState; #[cfg(feature = "flakes")] @@ -16,8 +18,8 @@ use crate::util::{panic_issue_call_failed, wrap}; /// the evaluation state. /// pub struct EvalStateBuilder { - inner: NonNull, - store: Store, + inner: Rc>>, + store: Rc>, } // impl Clone for EvalStateBuilder { @@ -39,17 +41,17 @@ pub struct EvalStateBuilder { impl AsInnerPtr for EvalStateBuilder { #[inline] unsafe fn as_ptr(&self) -> *mut sys::nix_eval_state_builder { - self.inner.as_ptr() + self.inner.borrow().as_ptr() } #[inline] unsafe fn as_ref(&self) -> &sys::nix_eval_state_builder { - unsafe { self.inner.as_ref() } + unsafe { self.inner.borrow().as_ref() } } #[inline] unsafe fn as_mut(&mut self) -> &mut sys::nix_eval_state_builder { - unsafe { self.inner.as_mut() } + unsafe { self.inner.borrow_mut().as_mut() } } } @@ -64,14 +66,14 @@ impl EvalStateBuilder { /// /// Returns an error if the builder cannot be created. /// - pub fn new(store: &Store) -> NixideResult { + pub fn new(store: Rc>) -> NixideResult { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_eval_state_builder_new(ctx.as_ptr(), store.as_ptr()) + sys::nix_eval_state_builder_new(ctx.as_ptr(), store.borrow().as_ptr()) })?; Ok(EvalStateBuilder { - inner, - store: store.clone(), + inner: Rc::new(RefCell::new(inner)), + store, }) } @@ -87,7 +89,7 @@ impl EvalStateBuilder { sys::nix_eval_state_build(ctx.as_ptr(), self.as_ptr()) })?; - Ok(EvalState::new(inner, &self.store)) + Ok(EvalState::from(inner, self.store.clone())) } // XXX: TODO: use `flakes()` instead diff --git a/nixide/src/expr/realised_string.rs b/nixide/src/expr/realised_string.rs index 5d5e08f..0d41b6f 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, c_void}; +use std::ffi::c_char; 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,23 +17,6 @@ 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 { @@ -63,7 +46,7 @@ impl<'a> RealisedString<'a> { /// Realise a string context. /// /// This will - /// - realise the store paths referenced by the string's context, and + /// - realise the store paths referenced by the string's content, and /// - perform the replacement of placeholders. /// - create temporary garbage collection roots for the store paths, for /// the lifetime of the current process. @@ -77,9 +60,6 @@ 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( @@ -89,21 +69,20 @@ 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: cell, - path: Self::parse_path(inner.as_ptr(), state), + inner: RefCell::new(inner), + path: Self::parse_path(inner.as_ptr(), &state.store_ref().borrow()), children: LazyArray::new( size, - Box::new(|_| StorePath::fake_path(state.store_ref()).unwrap()), + Box::new(|_| StorePath::fake_path(&state.store_ref().borrow()).unwrap()), ), }) } - fn parse_path(realised_string: *mut sys::nix_realised_string, state: &EvalState) -> StorePath { + fn parse_path(realised_string: *mut sys::nix_realised_string, store: &Store) -> 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) }; @@ -115,7 +94,7 @@ impl<'a> RealisedString<'a> { err ) }); - StorePath::parse(state.store_ref(), &path_str).unwrap_or_else(|err| { + StorePath::parse(store, &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 5233ea2..e9342d0 100644 --- a/nixide/src/expr/tests.rs +++ b/nixide/src/expr/tests.rs @@ -1,5 +1,3 @@ -use std::rc::Rc; - use serial_test::serial; use super::{EvalStateBuilder, Value}; @@ -8,19 +6,18 @@ use crate::Store; #[test] #[serial] fn test_eval_state_builder() { - let store = Rc::new(Store::default().expect("Failed to open store")); - let _state = EvalStateBuilder::new(&store) + let store = Store::default().expect("Failed to open store"); + let _state = EvalStateBuilder::new(store.clone()) .expect("Failed to create builder") .build() .expect("Failed to build state"); - // State should be dropped automatically } #[test] #[serial] fn test_simple_evaluation() { - let store = Rc::new(Store::default().expect("Failed to open store")); - let state = EvalStateBuilder::new(&store) + let store = Store::default().expect("Failed to open store"); + let state = EvalStateBuilder::new(store.clone()) .expect("Failed to create builder") .build() .expect("Failed to build state"); @@ -41,7 +38,7 @@ fn test_simple_evaluation() { #[serial] fn test_value_types() { let store = Store::default().expect("Failed to open store"); - let state = EvalStateBuilder::new(&store) + let state = EvalStateBuilder::new(store.clone()) .expect("Failed to create builder") .build() .expect("Failed to build state"); @@ -84,7 +81,7 @@ fn test_value_types() { #[serial] fn test_value_formatting() { let store = Store::default().expect("Failed to open store"); - let state = EvalStateBuilder::new(&store) + let state = EvalStateBuilder::new(store.clone()) .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 9f8f8e4..4a3c2dd 100644 --- a/nixide/src/expr/values/attrs.rs +++ b/nixide/src/expr/values/attrs.rs @@ -1,5 +1,7 @@ +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::errors::{ErrorContext, NixideError}; @@ -11,7 +13,7 @@ use crate::{EvalState, NixError}; pub struct NixAttrs { inner: NonNull, - state: EvalState, + state: Rc>>, len: u32, } @@ -84,7 +86,7 @@ impl NixValue for NixAttrs { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), len, } } @@ -107,7 +109,7 @@ impl NixAttrs { sys::nix_get_attr_byidx( ctx.as_ptr(), self.as_ptr(), - self.state.as_ptr(), + self.state.borrow().as_ptr(), index, name_ptr, ) @@ -134,7 +136,7 @@ impl NixAttrs { sys::nix_get_attr_byidx_lazy( ctx.as_ptr(), self.as_ptr(), - self.state.as_ptr(), + self.state.borrow().as_ptr(), index, name_ptr, ) @@ -156,7 +158,12 @@ 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.as_ptr(), index) + sys::nix_get_attr_name_byidx( + ctx.as_ptr(), + self.as_ptr(), + self.state.borrow().as_ptr(), + index, + ) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); @@ -175,7 +182,7 @@ impl NixAttrs { sys::nix_get_attr_byname( ctx.as_ptr(), self.as_ptr(), - self.state.as_ptr(), + self.state.borrow().as_ptr(), name.as_ref() .into_c_ptr() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)), @@ -201,7 +208,7 @@ impl NixAttrs { sys::nix_get_attr_byname_lazy( ctx.as_ptr(), self.as_ptr(), - self.state.as_ptr(), + self.state.borrow().as_ptr(), name.as_ref() .into_c_ptr() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)), diff --git a/nixide/src/expr/values/bool.rs b/nixide/src/expr/values/bool.rs index dd04031..0fdb0d8 100644 --- a/nixide/src/expr/values/bool.rs +++ b/nixide/src/expr/values/bool.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::{EvalState, sys}; pub struct NixBool { inner: NonNull, - state: EvalState, + state: Rc>>, value: bool, } @@ -85,7 +87,7 @@ impl NixValue for NixBool { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), value, } } diff --git a/nixide/src/expr/values/float.rs b/nixide/src/expr/values/float.rs index 9538b45..54b6e11 100644 --- a/nixide/src/expr/values/float.rs +++ b/nixide/src/expr/values/float.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixFloat { inner: NonNull, - state: EvalState, + state: Rc>>, value: f64, } @@ -85,7 +87,7 @@ impl NixValue for NixFloat { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), value, } } diff --git a/nixide/src/expr/values/function.rs b/nixide/src/expr/values/function.rs index 83d7d2a..cbf676e 100644 --- a/nixide/src/expr/values/function.rs +++ b/nixide/src/expr/values/function.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::{EvalState, sys}; pub struct NixFunction { inner: NonNull, - state: EvalState, + state: Rc>>, } impl Clone for NixFunction { @@ -76,7 +78,7 @@ impl NixValue for NixFunction { fn from(inner: NonNull, state: &EvalState) -> Self { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), } } } @@ -87,14 +89,14 @@ impl NixFunction { T: NixValue, { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr()) + sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().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.as_ptr(), + self.state.borrow().as_ptr(), self.as_ptr(), arg.as_ptr(), inner.as_ptr(), @@ -110,14 +112,14 @@ impl NixFunction { T: NixValue, { let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr()) + sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().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.as_ptr(), + self.state.borrow().as_ptr(), self.as_ptr(), args.len(), args.into_c_array(), diff --git a/nixide/src/expr/values/int.rs b/nixide/src/expr/values/int.rs index 86e5e94..7d7fe03 100644 --- a/nixide/src/expr/values/int.rs +++ b/nixide/src/expr/values/int.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixInt { inner: NonNull, - state: EvalState, + state: Rc>>, value: i64, } @@ -83,7 +85,7 @@ impl NixValue for NixInt { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), value, } } diff --git a/nixide/src/expr/values/list.rs b/nixide/src/expr/values/list.rs index 4c0f354..4d0264f 100644 --- a/nixide/src/expr/values/list.rs +++ b/nixide/src/expr/values/list.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixList { inner: NonNull, - state: EvalState, + state: Rc>>, } impl Clone for NixList { @@ -76,7 +78,7 @@ impl NixValue for NixList { fn from(inner: NonNull, state: &EvalState) -> Self { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), } } } @@ -116,7 +118,12 @@ 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.as_ptr(), index) + sys::nix_get_list_byidx( + ctx.as_ptr(), + self.as_ptr(), + self.state.borrow().as_ptr(), + index, + ) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); @@ -125,7 +132,12 @@ impl NixList { 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.as_ptr(), index) + sys::nix_get_list_byidx_lazy( + ctx.as_ptr(), + self.as_ptr(), + self.state.borrow().as_ptr(), + index, + ) }) .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 fd20445..bccbe70 100644 --- a/nixide/src/expr/values/null.rs +++ b/nixide/src/expr/values/null.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::util::wrappers::AsInnerPtr; pub struct NixNull { inner: NonNull, - state: EvalState, + state: Rc>>, } impl Clone for NixNull { @@ -76,7 +78,7 @@ impl NixValue for NixNull { fn from(inner: NonNull, state: &EvalState) -> Self { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), } } } diff --git a/nixide/src/expr/values/path.rs b/nixide/src/expr/values/path.rs index 6d51fd6..0ba968c 100644 --- a/nixide/src/expr/values/path.rs +++ b/nixide/src/expr/values/path.rs @@ -1,6 +1,8 @@ +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; @@ -12,7 +14,7 @@ use crate::{EvalState, sys}; pub struct NixPath { inner: NonNull, - state: EvalState, + state: Rc>>, value: PathBuf, } @@ -87,7 +89,7 @@ impl NixValue for NixPath { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), value, } } diff --git a/nixide/src/expr/values/string.rs b/nixide/src/expr/values/string.rs index 765d763..20864b9 100644 --- a/nixide/src/expr/values/string.rs +++ b/nixide/src/expr/values/string.rs @@ -1,5 +1,8 @@ +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; @@ -10,7 +13,7 @@ use crate::{EvalState, sys}; pub struct NixString { inner: NonNull, - state: EvalState, + state: Rc>>, value: String, } @@ -90,7 +93,7 @@ impl NixValue for NixString { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), value, } } diff --git a/nixide/src/expr/values/thunk.rs b/nixide/src/expr/values/thunk.rs index b6439ce..c7f0cb3 100644 --- a/nixide/src/expr/values/thunk.rs +++ b/nixide/src/expr/values/thunk.rs @@ -1,5 +1,7 @@ +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; @@ -10,7 +12,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixThunk { inner: NonNull, - state: EvalState, + state: Rc>>, } impl Clone for NixThunk { @@ -76,7 +78,7 @@ impl NixValue for NixThunk { fn from(inner: NonNull, state: &EvalState) -> Self { Self { inner, - state: state.clone(), + state: state.inner_ref().clone(), } } } @@ -84,7 +86,11 @@ impl NixValue for NixThunk { impl NixThunk { pub fn eval(self) -> Value { wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_value_force(ctx.as_ptr(), self.state.as_ptr(), self.inner.as_ptr()) + sys::nix_value_force( + ctx.as_ptr(), + self.state.borrow().as_ptr(), + self.inner.as_ptr(), + ) }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); diff --git a/nixide/src/flake/fetchers_settings.rs b/nixide/src/flake/fetchers_settings.rs index 1f24d04..cf15df2 100644 --- a/nixide/src/flake/fetchers_settings.rs +++ b/nixide/src/flake/fetchers_settings.rs @@ -1,4 +1,3 @@ -use std::ffi::c_void; use std::ptr::NonNull; use crate::NixideResult; diff --git a/nixide/src/store/mod.rs b/nixide/src/store/mod.rs index 35c04e8..f40a395 100644 --- a/nixide/src/store/mod.rs +++ b/nixide/src/store/mod.rs @@ -7,9 +7,11 @@ 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; @@ -68,24 +70,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(Store { inner }) + Ok(Rc::new(RefCell::new(Store { inner }))) } /// Realize a store path. From f96f1cf95e22049c0f27723649d25164a168e7a4 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 31 Mar 2026 08:11:17 +1000 Subject: [PATCH 2/3] vaues now use Rc>> --- nixide/src/expr/eval_state.rs | 2 +- nixide/src/expr/eval_state_builder.rs | 16 ---------------- nixide/src/expr/values/attrs.rs | 18 +++++++----------- nixide/src/expr/values/bool.rs | 6 +++--- nixide/src/expr/values/float.rs | 5 ++--- nixide/src/expr/values/function.rs | 13 +++++-------- nixide/src/expr/values/int.rs | 5 ++--- nixide/src/expr/values/list.rs | 12 ++++-------- nixide/src/expr/values/mod.rs | 21 ++++++++++++++++----- nixide/src/expr/values/null.rs | 8 ++------ nixide/src/expr/values/path.rs | 6 +++--- nixide/src/expr/values/string.rs | 6 +++--- nixide/src/expr/values/thunk.rs | 10 +++------- nixide/src/flake/flake_settings.rs | 14 -------------- nixide/src/flake/locked_flake.rs | 13 ++++++------- nixide/src/store/tests.rs | 8 +++----- 16 files changed, 60 insertions(+), 103 deletions(-) diff --git a/nixide/src/expr/eval_state.rs b/nixide/src/expr/eval_state.rs index 0103416..10644fb 100644 --- a/nixide/src/expr/eval_state.rs +++ b/nixide/src/expr/eval_state.rs @@ -101,7 +101,7 @@ impl EvalState { sys::nix_expr_eval_from_string(ctx.as_ptr(), self.as_ptr(), expr, path, value.as_ptr()); value }) - .map(|ptr| Value::from((ptr, self))) + .map(|ptr| Value::from((ptr, self.inner_ref().clone()))) } } diff --git a/nixide/src/expr/eval_state_builder.rs b/nixide/src/expr/eval_state_builder.rs index af4fd7d..2ae0056 100644 --- a/nixide/src/expr/eval_state_builder.rs +++ b/nixide/src/expr/eval_state_builder.rs @@ -22,22 +22,6 @@ pub struct EvalStateBuilder { store: Rc>, } -// 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 { diff --git a/nixide/src/expr/values/attrs.rs b/nixide/src/expr/values/attrs.rs index 4a3c2dd..0213e54 100644 --- a/nixide/src/expr/values/attrs.rs +++ b/nixide/src/expr/values/attrs.rs @@ -4,12 +4,12 @@ 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, @@ -78,17 +78,13 @@ impl NixValue for NixAttrs { sys::ValueType_NIX_TYPE_ATTRS } - fn from(inner: NonNull, state: &EvalState) -> Self { + fn from(inner: NonNull, state: Rc>>) -> 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: state.inner_ref().clone(), - len, - } + Self { inner, state, len } } } @@ -120,7 +116,7 @@ impl NixAttrs { .to_utf8_string() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - let value = Value::from((inner, &self.state)); + let value = Value::from((inner, self.state.clone())); Some((name, value)) } @@ -147,7 +143,7 @@ impl NixAttrs { .to_utf8_string() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - let value = ::from(inner, &self.state); + let value = ::from(inner, self.state.clone()); Some((name, value)) } @@ -190,7 +186,7 @@ impl NixAttrs { }); match result { - Ok(inner) => Some(Value::from((inner, &self.state))), + Ok(inner) => Some(Value::from((inner, self.state.clone()))), Err(NixideError::NixError { err: NixError::KeyNotFound(_), @@ -216,7 +212,7 @@ impl NixAttrs { }); match result { - Ok(inner) => Some(::from(inner, &self.state)), + Ok(inner) => Some(::from(inner, self.state.clone())), Err(NixideError::NixError { err: NixError::KeyNotFound(_), diff --git a/nixide/src/expr/values/bool.rs b/nixide/src/expr/values/bool.rs index 0fdb0d8..54fcade 100644 --- a/nixide/src/expr/values/bool.rs +++ b/nixide/src/expr/values/bool.rs @@ -5,10 +5,10 @@ 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, @@ -77,7 +77,7 @@ impl NixValue for NixBool { sys::ValueType_NIX_TYPE_BOOL } - fn from(inner: NonNull, state: &EvalState) -> Self { + fn from(inner: NonNull, state: Rc>>) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_bool(ctx.as_ptr(), inner.as_ptr()) }) @@ -87,7 +87,7 @@ impl NixValue for NixBool { Self { inner, - state: state.inner_ref().clone(), + state, value, } } diff --git a/nixide/src/expr/values/float.rs b/nixide/src/expr/values/float.rs index 54b6e11..3b0be68 100644 --- a/nixide/src/expr/values/float.rs +++ b/nixide/src/expr/values/float.rs @@ -4,7 +4,6 @@ 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; @@ -77,7 +76,7 @@ impl NixValue for NixFloat { sys::ValueType_NIX_TYPE_FLOAT } - fn from(inner: NonNull, state: &EvalState) -> Self { + fn from(inner: NonNull, state: Rc>>) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_float(ctx.as_ptr(), inner.as_ptr()) }) @@ -87,7 +86,7 @@ impl NixValue for NixFloat { Self { inner, - state: state.inner_ref().clone(), + state, value, } } diff --git a/nixide/src/expr/values/function.rs b/nixide/src/expr/values/function.rs index cbf676e..5ed9a18 100644 --- a/nixide/src/expr/values/function.rs +++ b/nixide/src/expr/values/function.rs @@ -6,9 +6,9 @@ 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, @@ -75,11 +75,8 @@ impl NixValue for NixFunction { sys::ValueType_NIX_TYPE_FUNCTION } - fn from(inner: NonNull, state: &EvalState) -> Self { - Self { - inner, - state: state.inner_ref().clone(), - } + fn from(inner: NonNull, state: Rc>>) -> Self { + Self { inner, state } } } @@ -104,7 +101,7 @@ impl NixFunction { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((inner, &self.state)) + Value::from((inner, self.state.clone())) } pub fn call_many(&self, args: &[&T]) -> Value @@ -128,7 +125,7 @@ impl NixFunction { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((inner, &self.state)) + Value::from((inner, self.state.clone())) } } diff --git a/nixide/src/expr/values/int.rs b/nixide/src/expr/values/int.rs index 7d7fe03..815edef 100644 --- a/nixide/src/expr/values/int.rs +++ b/nixide/src/expr/values/int.rs @@ -4,7 +4,6 @@ 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; @@ -77,7 +76,7 @@ impl NixValue for NixInt { sys::ValueType_NIX_TYPE_INT } - fn from(inner: NonNull, state: &EvalState) -> Self { + fn from(inner: NonNull, state: Rc>>) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_int(ctx.as_ptr(), inner.as_ptr()) }) @@ -85,7 +84,7 @@ impl NixValue for NixInt { Self { inner, - state: state.inner_ref().clone(), + state, value, } } diff --git a/nixide/src/expr/values/list.rs b/nixide/src/expr/values/list.rs index 4d0264f..7172f8b 100644 --- a/nixide/src/expr/values/list.rs +++ b/nixide/src/expr/values/list.rs @@ -4,7 +4,6 @@ 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; @@ -75,11 +74,8 @@ impl NixValue for NixList { sys::ValueType_NIX_TYPE_LIST } - fn from(inner: NonNull, state: &EvalState) -> Self { - Self { - inner, - state: state.inner_ref().clone(), - } + fn from(inner: NonNull, state: Rc>>) -> Self { + Self { inner, state } } } @@ -127,7 +123,7 @@ impl NixList { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((inner, &self.state)) + Value::from((inner, self.state.clone())) } pub fn get_lazy(&self, index: u32) -> NixThunk { @@ -141,6 +137,6 @@ impl NixList { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - ::from(inner, &self.state) + ::from(inner, self.state.clone()) } } diff --git a/nixide/src/expr/values/mod.rs b/nixide/src/expr/values/mod.rs index f6f6b80..a06edde 100644 --- a/nixide/src/expr/values/mod.rs +++ b/nixide/src/expr/values/mod.rs @@ -23,10 +23,11 @@ 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::{ @@ -43,7 +44,7 @@ pub trait NixValue: Clone + Drop + Display + Debug + AsInnerPtr fn type_id(&self) -> sys::ValueType; /// TODO - fn from(inner: NonNull, state: &EvalState) -> Self; + fn from(inner: NonNull, state: Rc>>) -> Self; } /// A Nix value @@ -109,12 +110,22 @@ pub enum Value { // Failed(NixFailed), } -impl From<(NonNull, &EvalState)> for Value { - fn from(value: (NonNull, &EvalState)) -> Self { +impl + From<( + NonNull, + Rc>>, + )> for Value +{ + fn from( + value: ( + NonNull, + Rc>>, + ), + ) -> Self { let (inner, state) = value; wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_value_force(ctx.as_ptr(), state.as_ptr(), inner.as_ptr()) + sys::nix_value_force(ctx.as_ptr(), state.borrow().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 bccbe70..46bfe15 100644 --- a/nixide/src/expr/values/null.rs +++ b/nixide/src/expr/values/null.rs @@ -4,7 +4,6 @@ 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; @@ -75,10 +74,7 @@ impl NixValue for NixNull { sys::ValueType_NIX_TYPE_NULL } - fn from(inner: NonNull, state: &EvalState) -> Self { - Self { - inner, - state: state.inner_ref().clone(), - } + fn from(inner: NonNull, state: Rc>>) -> Self { + Self { inner, state } } } diff --git a/nixide/src/expr/values/path.rs b/nixide/src/expr/values/path.rs index 0ba968c..f9a49a0 100644 --- a/nixide/src/expr/values/path.rs +++ b/nixide/src/expr/values/path.rs @@ -7,10 +7,10 @@ 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, @@ -79,7 +79,7 @@ impl NixValue for NixPath { sys::ValueType_NIX_TYPE_PATH } - fn from(inner: NonNull, state: &EvalState) -> Self { + fn from(inner: NonNull, state: Rc>>) -> Self { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { sys::nix_get_path_string(ctx.as_ptr(), inner.as_ptr()) }) @@ -89,7 +89,7 @@ impl NixValue for NixPath { Self { inner, - state: state.inner_ref().clone(), + state, value, } } diff --git a/nixide/src/expr/values/string.rs b/nixide/src/expr/values/string.rs index 20864b9..d2582de 100644 --- a/nixide/src/expr/values/string.rs +++ b/nixide/src/expr/values/string.rs @@ -6,10 +6,10 @@ 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, @@ -78,7 +78,7 @@ impl NixValue for NixString { sys::ValueType_NIX_TYPE_STRING } - fn from(inner: NonNull, state: &EvalState) -> Self { + fn from(inner: NonNull, state: Rc>>) -> Self { let value = wrap::nix_string_callback!( |callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { sys::nix_get_string( @@ -93,7 +93,7 @@ impl NixValue for NixString { Self { inner, - state: state.inner_ref().clone(), + state, value, } } diff --git a/nixide/src/expr/values/thunk.rs b/nixide/src/expr/values/thunk.rs index c7f0cb3..294745e 100644 --- a/nixide/src/expr/values/thunk.rs +++ b/nixide/src/expr/values/thunk.rs @@ -4,7 +4,6 @@ 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; @@ -75,11 +74,8 @@ impl NixValue for NixThunk { sys::ValueType_NIX_TYPE_THUNK } - fn from(inner: NonNull, state: &EvalState) -> Self { - Self { - inner, - state: state.inner_ref().clone(), - } + fn from(inner: NonNull, state: Rc>>) -> Self { + Self { inner, state } } } @@ -94,6 +90,6 @@ impl NixThunk { }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - Value::from((self.inner, &self.state)) + Value::from((self.inner, self.state.clone())) } } diff --git a/nixide/src/flake/flake_settings.rs b/nixide/src/flake/flake_settings.rs index 295115b..9d11358 100644 --- a/nixide/src/flake/flake_settings.rs +++ b/nixide/src/flake/flake_settings.rs @@ -1,4 +1,3 @@ -use std::ffi::c_void; use std::ptr::NonNull; use crate::NixideResult; @@ -20,19 +19,6 @@ 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 a2ae9af..4f0237c 100644 --- a/nixide/src/flake/locked_flake.rs +++ b/nixide/src/flake/locked_flake.rs @@ -1,6 +1,5 @@ // 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}; @@ -130,8 +129,8 @@ mod tests { fn flake_settings_getflake_exists() { init(); - let store = Store::default().expect("Failed to open store connection"); - let state = EvalStateBuilder::new(&store) + let store_ref = Store::default().expect("Failed to open store connection"); + let state = EvalStateBuilder::new(store_ref.clone()) .unwrap() .flakes() .unwrap() @@ -165,10 +164,10 @@ mod tests { ) .unwrap(); - let store = Store::default().unwrap(); + let store_ref = Store::default().unwrap(); let flake_settings = FlakeSettings::new().unwrap(); - let mut eval_state = EvalStateBuilder::new(&store) + let mut eval_state = EvalStateBuilder::new(store_ref.clone()) .unwrap() .set_flake_settings(&flake_settings) .unwrap() @@ -214,10 +213,10 @@ mod tests { fn flake_lock_load_flake_with_flags() { init(); - let store = Store::default().unwrap(); + let store_ref = Store::default().unwrap(); let fetchers_settings = FetchersSettings::new().unwrap(); let flake_settings = FlakeSettings::new().unwrap(); - let mut eval_state = EvalStateBuilder::new(&store) + let mut eval_state = EvalStateBuilder::new(store_ref.clone()) .unwrap() .set_flake_settings(&flake_settings) .unwrap() diff --git a/nixide/src/store/tests.rs b/nixide/src/store/tests.rs index 5943077..1a9c3ac 100644 --- a/nixide/src/store/tests.rs +++ b/nixide/src/store/tests.rs @@ -1,10 +1,7 @@ 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] @@ -22,7 +19,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); + let result = StorePath::fake_path(&store.borrow()); result.expect("idk hopefully this fails"); } @@ -34,7 +31,8 @@ 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).expect("Failed to create `StorePath::fake_path`"); + let path = + StorePath::fake_path(&store.borrow()).expect("Failed to create `StorePath::fake_path`"); let cloned = path.clone(); // Assert that the cloned path has the same name as the original From 599c783d01617a8b3f1fae93ec4e2ef3e37e0c51 Mon Sep 17 00:00:00 2001 From: _cry64 Date: Tue, 31 Mar 2026 08:12:25 +1000 Subject: [PATCH 3/3] make build.rs prettier --- flake.nix | 9 ++++- nixide-sys/build.rs | 92 +++++++++++++++++---------------------------- 2 files changed, 43 insertions(+), 58 deletions(-) diff --git a/flake.nix b/flake.nix index 30f7a1d..49560e3 100644 --- a/flake.nix +++ b/flake.nix @@ -24,6 +24,7 @@ allowUnfree = false; allowBroken = false; overlays = builtins.attrValues self.overlays or {}; + # config.replaceStdenv = {pkgs}: with pkgs; llvmPackages_21.stdenv; }; forAllSystems = f: @@ -60,13 +61,19 @@ packages = with pkgs; [ rustc llvmPackages.lld - lldb + llvmPackages.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 23c0e7c..1fee802 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,31 +18,26 @@ 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 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"); + // Invalidate the built crate if the binding headers change + // println!("cargo::rerun-if-changed=include"); - 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 + let lib_args: Vec = LIBS .iter() .map(|&name| { let lib = pkg_config::probe_library(name) @@ -57,52 +52,35 @@ 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()); - // 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"); + // 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)); // 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!");