diff --git a/rust/nix-expr/src/eval_state.rs b/rust/nix-expr/src/eval_state.rs index 6ff4d54..1559727 100644 --- a/rust/nix-expr/src/eval_state.rs +++ b/rust/nix-expr/src/eval_state.rs @@ -1,4 +1,4 @@ -use crate::value::{Value, ValueType}; +use crate::value::{Int, Value, ValueType}; use anyhow::Context as _; use anyhow::{bail, Result}; use lazy_static::lazy_static; @@ -115,6 +115,15 @@ impl EvalState { let r = unsafe { raw::get_type(self.context.ptr(), value.raw_ptr()) }; Ok(ValueType::from_raw(r)) } + pub fn require_int(&self, v: &Value) -> Result { + let t = self.value_type(v).unwrap(); + if t != ValueType::Int { + bail!("expected an int, but got a {:?}", t); + } + let i = unsafe { raw::get_int(self.context.ptr(), v.raw_ptr()) }; + Ok(i) + } + /// Not exposed, because the caller must always explicitly handle the context or not accept one at all. fn get_string(&self, value: &Value) -> Result { let mut r = result_string_init!(); @@ -302,6 +311,21 @@ mod tests { .unwrap(); } + #[test] + fn eval_state_value_int() { + gc_registering_current_thread(|| { + let store = Store::open("auto").unwrap(); + let es = EvalState::new(store).unwrap(); + let v = es.eval_from_string("1", "").unwrap(); + es.force(&v).unwrap(); + let t = es.value_type(&v).unwrap(); + assert!(t == ValueType::Int); + let i = es.require_int(&v).unwrap(); + assert!(i == 1); + }) + .unwrap(); + } + #[test] fn eval_state_value_string() { gc_registering_current_thread(|| { diff --git a/rust/nix-expr/src/value.rs b/rust/nix-expr/src/value.rs index f1211e3..88f5f76 100644 --- a/rust/nix-expr/src/value.rs +++ b/rust/nix-expr/src/value.rs @@ -4,6 +4,8 @@ use std::ptr::{null_mut, NonNull}; // TODO: test: cloning a thunk does not duplicate the evaluation. +pub type Int = i64; + /** The type of a value (or thunk) */ #[derive(Eq, PartialEq, Debug)] pub enum ValueType {