diff --git a/rust/nix-expr/src/eval_state.rs b/rust/nix-expr/src/eval_state.rs index 633eb57..7510cfa 100644 --- a/rust/nix-expr/src/eval_state.rs +++ b/rust/nix-expr/src/eval_state.rs @@ -1,4 +1,4 @@ -use crate::value::{Int, Value, ValueType}; +use crate::value::{Int, Value, ValueType, ValueTypeOrThunk}; use anyhow::Context as _; use anyhow::{bail, Result}; use lazy_static::lazy_static; @@ -133,19 +133,24 @@ impl EvalState { } self.context.check_err() } - pub fn value_is_thunk(&self, value: &Value) -> bool { - let r = unsafe { - raw::get_type(self.context.ptr(), value.raw_ptr()) == raw::ValueType_NIX_TYPE_THUNK - }; - self.context.check_err().unwrap(); - r - } - pub fn value_type(&self, value: &Value) -> Result { - if self.value_is_thunk(value) { - self.force(value)?; - } + pub fn value_type_unforced(&self, value: &Value) -> ValueTypeOrThunk { let r = unsafe { raw::get_type(self.context.ptr(), value.raw_ptr()) }; - Ok(ValueType::from_raw(r)) + self.context.check_err().unwrap(); + ValueTypeOrThunk::from_raw(r) + } + pub fn value_type_forced(&self, value: &Value) -> Result { + match self.value_type_unforced(value) { + ValueTypeOrThunk::ValueType(a) => Ok(a), + ValueTypeOrThunk::Thunk => { + self.force(value)?; + match self.value_type_unforced(value) { + ValueTypeOrThunk::ValueType(a) => Ok(a), + ValueTypeOrThunk::Thunk => { + panic!("values should not be thunks after having been forced.") + } + } + } + } } pub fn require_int(&self, v: &Value) -> Result { let t = self.value_type(v).unwrap(); diff --git a/rust/nix-expr/src/value.rs b/rust/nix-expr/src/value.rs index 46371a2..dfc160e 100644 --- a/rust/nix-expr/src/value.rs +++ b/rust/nix-expr/src/value.rs @@ -19,26 +19,31 @@ pub enum ValueType { Null, Path, String, - Thunk, Unknown, } -impl ValueType { - pub(crate) fn from_raw(raw: raw::ValueType) -> ValueType { +#[derive(Eq, PartialEq, Debug)] +pub enum ValueTypeOrThunk { + ValueType(ValueType), + Thunk, +} + +impl ValueTypeOrThunk { + pub(crate) fn from_raw(raw: raw::ValueType) -> ValueTypeOrThunk { match raw { - raw::ValueType_NIX_TYPE_ATTRS => ValueType::AttrSet, - raw::ValueType_NIX_TYPE_BOOL => ValueType::Bool, - raw::ValueType_NIX_TYPE_EXTERNAL => ValueType::External, - raw::ValueType_NIX_TYPE_FLOAT => ValueType::Float, - raw::ValueType_NIX_TYPE_FUNCTION => ValueType::Function, - raw::ValueType_NIX_TYPE_INT => ValueType::Int, - raw::ValueType_NIX_TYPE_LIST => ValueType::List, - raw::ValueType_NIX_TYPE_NULL => ValueType::Null, - raw::ValueType_NIX_TYPE_PATH => ValueType::Path, - raw::ValueType_NIX_TYPE_STRING => ValueType::String, - raw::ValueType_NIX_TYPE_THUNK => ValueType::Thunk, + raw::ValueType_NIX_TYPE_ATTRS => ValueTypeOrThunk::ValueType(ValueType::AttrSet), + raw::ValueType_NIX_TYPE_BOOL => ValueTypeOrThunk::ValueType(ValueType::Bool), + raw::ValueType_NIX_TYPE_EXTERNAL => ValueTypeOrThunk::ValueType(ValueType::External), + raw::ValueType_NIX_TYPE_FLOAT => ValueTypeOrThunk::ValueType(ValueType::Float), + raw::ValueType_NIX_TYPE_FUNCTION => ValueTypeOrThunk::ValueType(ValueType::Function), + raw::ValueType_NIX_TYPE_INT => ValueTypeOrThunk::ValueType(ValueType::Int), + raw::ValueType_NIX_TYPE_LIST => ValueTypeOrThunk::ValueType(ValueType::List), + raw::ValueType_NIX_TYPE_NULL => ValueTypeOrThunk::ValueType(ValueType::Null), + raw::ValueType_NIX_TYPE_PATH => ValueTypeOrThunk::ValueType(ValueType::Path), + raw::ValueType_NIX_TYPE_STRING => ValueTypeOrThunk::ValueType(ValueType::String), + raw::ValueType_NIX_TYPE_THUNK => ValueTypeOrThunk::Thunk, // This would happen if a new type of value is added in Nix. - _ => ValueType::Unknown, + _ => ValueTypeOrThunk::ValueType(ValueType::Unknown), } } }