2024-03-19 14:43:01 +01:00
|
|
|
use nix_c_raw as raw;
|
|
|
|
|
use nix_util::context::Context;
|
2024-05-09 12:41:34 -04:00
|
|
|
use std::ptr::{null_mut, NonNull};
|
2024-03-19 14:43:01 +01:00
|
|
|
|
|
|
|
|
// TODO: test: cloning a thunk does not duplicate the evaluation.
|
|
|
|
|
|
2024-04-09 13:13:52 +02:00
|
|
|
pub type Int = i64;
|
|
|
|
|
|
2024-05-24 11:15:43 +02:00
|
|
|
/// The type of a value (or thunk)
|
2024-04-04 16:38:12 +02:00
|
|
|
#[derive(Eq, PartialEq, Debug)]
|
2024-03-19 14:43:01 +01:00
|
|
|
pub enum ValueType {
|
|
|
|
|
AttrSet,
|
|
|
|
|
Bool,
|
|
|
|
|
External,
|
|
|
|
|
Float,
|
|
|
|
|
Function,
|
|
|
|
|
Int,
|
|
|
|
|
List,
|
|
|
|
|
Null,
|
|
|
|
|
Path,
|
|
|
|
|
String,
|
|
|
|
|
Unknown,
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-14 18:42:23 +02:00
|
|
|
impl ValueType {
|
|
|
|
|
/// Convert a raw value type to a `ValueType`.
|
|
|
|
|
///
|
|
|
|
|
/// Return `None` if the Value is still a thunk (i.e. not yet evaluated).
|
|
|
|
|
///
|
|
|
|
|
/// Return `Some(ValueType::Unknown)` if the value type is not recognized.
|
|
|
|
|
pub(crate) fn from_raw(raw: raw::ValueType) -> Option<ValueType> {
|
2024-03-19 14:43:01 +01:00
|
|
|
match raw {
|
2024-06-14 18:42:23 +02:00
|
|
|
raw::ValueType_NIX_TYPE_ATTRS => Some(ValueType::AttrSet),
|
|
|
|
|
raw::ValueType_NIX_TYPE_BOOL => Some(ValueType::Bool),
|
|
|
|
|
raw::ValueType_NIX_TYPE_EXTERNAL => Some(ValueType::External),
|
|
|
|
|
raw::ValueType_NIX_TYPE_FLOAT => Some(ValueType::Float),
|
|
|
|
|
raw::ValueType_NIX_TYPE_FUNCTION => Some(ValueType::Function),
|
|
|
|
|
raw::ValueType_NIX_TYPE_INT => Some(ValueType::Int),
|
|
|
|
|
raw::ValueType_NIX_TYPE_LIST => Some(ValueType::List),
|
|
|
|
|
raw::ValueType_NIX_TYPE_NULL => Some(ValueType::Null),
|
|
|
|
|
raw::ValueType_NIX_TYPE_PATH => Some(ValueType::Path),
|
|
|
|
|
raw::ValueType_NIX_TYPE_STRING => Some(ValueType::String),
|
|
|
|
|
|
|
|
|
|
raw::ValueType_NIX_TYPE_THUNK => None,
|
|
|
|
|
|
2024-05-09 12:41:34 -04:00
|
|
|
// This would happen if a new type of value is added in Nix.
|
2024-06-14 18:42:23 +02:00
|
|
|
_ => Some(ValueType::Unknown),
|
2024-03-19 14:43:01 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* A pointer to a value or thunk, to be used with EvalState methods. */
|
|
|
|
|
pub struct Value {
|
|
|
|
|
inner: NonNull<raw::Value>,
|
|
|
|
|
}
|
|
|
|
|
impl Value {
|
|
|
|
|
pub(crate) fn new(inner: *mut raw::Value) -> Self {
|
|
|
|
|
Value {
|
|
|
|
|
inner: NonNull::new(inner).unwrap(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub(crate) fn raw_ptr(&self) -> *mut raw::Value {
|
|
|
|
|
self.inner.as_ptr()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl Drop for Value {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
unsafe {
|
2024-05-09 12:41:34 -04:00
|
|
|
// ignoring error because the only failure mode is leaking memory
|
|
|
|
|
raw::gc_decref(null_mut(), self.inner.as_ptr());
|
2024-03-19 14:43:01 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl Clone for Value {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
let context = Context::new();
|
2024-05-09 12:29:32 -04:00
|
|
|
unsafe { raw::gc_incref(context.ptr(), self.inner.as_ptr()) };
|
2024-05-09 12:41:34 -04:00
|
|
|
// can't return an error here, but we don't want to ignore the error either as it means we could use-after-free
|
2024-03-19 14:43:01 +01:00
|
|
|
context.check_err().unwrap();
|
|
|
|
|
Value { inner: self.inner }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tested in eval_state.rs
|