Add API for adding new builtins

This commit is contained in:
2026-05-31 20:01:36 +02:00
parent 42f8eef0a8
commit af04dd9f58
2 changed files with 26 additions and 3 deletions
+12 -2
View File
@@ -207,6 +207,12 @@ pub struct RealisedString {
#[clippy::has_significant_drop]
struct EvalStateRef {
eval_state: NonNull<raw::EvalState>,
/// Whether we should call [`raw::state_free`] once this `EvalStateRef` is [`Drop`]ped.
///
/// The reason this exists is because we might construct non-owning [`EvalState`]s by way of
/// using [`EvalState::from_raw`], in which case we do not want to call [`raw::state_free`] once
/// the constructed [`EvalState`] goes out of scope.
should_free: bool,
}
unsafe impl Send for EvalStateRef {}
@@ -224,8 +230,10 @@ impl EvalStateRef {
impl Drop for EvalStateRef {
fn drop(&mut self) {
unsafe {
raw::state_free(self.eval_state.as_ptr());
if self.should_free {
unsafe {
raw::state_free(self.eval_state.as_ptr());
}
}
}
}
@@ -349,6 +357,7 @@ impl EvalStateBuilder {
eval_state: NonNull::new(eval_state).unwrap_or_else(|| {
panic!("nix_state_create returned a null pointer without an error")
}),
should_free: true,
},
})
}
@@ -394,6 +403,7 @@ impl EvalState {
eval_state: EvalStateRef {
eval_state: NonNull::new(ptr)
.expect("tried to construct a new `EvalState` from null pointer"),
should_free: false,
},
}
}
+14 -1
View File
@@ -92,7 +92,6 @@ impl PrimOp {
/// does not affect `builtins`.
#[doc(alias = "make_primop")]
#[doc(alias = "create_function")]
#[doc(alias = "builtin")]
pub fn new_value(self, eval_state: &mut EvalState) -> Result<Value, EvalStateError> {
let value = eval_state.new_value_uninitialized()?;
let mut ctx = Context::new();
@@ -101,6 +100,20 @@ impl PrimOp {
};
Ok(value)
}
/// Creates a new [`function`](crate::value::ValueType::Function) Nix value implemented by a
/// Rust function, and adds it to the global `builtins` attribute set.
///
/// Note that this `PrimOp` will only be accessible by [`EvalState`]s that are created _after_
/// this is called.
#[doc(alias = "builtin")]
pub fn new_builtin(self) -> Result<(), EvalStateError> {
let mut ctx = Context::new();
unsafe {
check_call!(raw::register_primop(&mut ctx, self.ptr))?;
}
Ok(())
}
}
/// The user_data for our Nix primops