diff --git a/nixide/Cargo.toml b/nixide/Cargo.toml index 3832ebc..6a64ced 100644 --- a/nixide/Cargo.toml +++ b/nixide/Cargo.toml @@ -16,7 +16,7 @@ path = "src/lib.rs" default = [] store = ["nixide-sys/nix-store-c"] exprs = ["store", "nixide-sys/nix-expr-c"] -flakes = ["exprs", "nixide-sys/nix-flake-c", "nixide-sys/nix-fetchers-c"] +flakes = ["store", "nixide-sys/nix-flake-c", "nixide-sys/nix-fetchers-c"] [dependencies] libc = "0.2.183" diff --git a/nixide/src/expr/eval_state.rs b/nixide/src/expr/evalstate.rs similarity index 77% rename from nixide/src/expr/eval_state.rs rename to nixide/src/expr/evalstate.rs index 3818d1a..4696549 100644 --- a/nixide/src/expr/eval_state.rs +++ b/nixide/src/expr/evalstate.rs @@ -1,12 +1,10 @@ -use std::cell::RefCell; use std::ffi::CString; use std::ptr::NonNull; -use std::rc::Rc; use std::sync::Arc; use crate::errors::new_nixide_error; -use super::Value; +use super::{NixValue, Value}; use crate::errors::ErrorContext; use crate::sys; use crate::util::wrappers::AsInnerPtr; @@ -18,7 +16,7 @@ use crate::{NixideResult, Store}; /// This provides the main interface for evaluating Nix expressions /// and creating values. pub struct EvalState { - inner: Rc>>, + inner: NonNull, // XXX: TODO: is an `Arc` necessary or just a `Store` store: Arc, @@ -27,32 +25,24 @@ pub struct EvalState { impl AsInnerPtr for EvalState { #[inline] unsafe fn as_ptr(&self) -> *mut sys::EvalState { - self.inner.borrow().as_ptr() + self.inner.as_ptr() } #[inline] unsafe fn as_ref(&self) -> &sys::EvalState { - unsafe { self.inner.borrow().as_ref() } + unsafe { self.inner.as_ref() } } #[inline] unsafe fn as_mut(&mut self) -> &mut sys::EvalState { - unsafe { self.inner.borrow_mut().as_mut() } + unsafe { self.inner.as_mut() } } } impl EvalState { /// Construct a new EvalState directly from its attributes pub(super) fn new(inner: NonNull, store: Arc) -> Self { - Self { - inner: Rc::new(RefCell::new(inner)), - store, - } - } - - #[inline] - pub(crate) fn inner_ref(&self) -> Rc>> { - self.inner.clone() + Self { inner, store } } #[inline] @@ -92,7 +82,22 @@ impl EvalState { ); value }) - .map(|ptr| Value::from((ptr, self.inner_ref()))) + .map(|ptr| Value::from((ptr, std::rc::Rc::new(std::cell::RefCell::new(self))))) + } + + /// Allocate a new value. + /// + /// # Errors + /// + /// Returns an error if value allocation fails. + pub(self) fn new_value(&self) -> NixideResult { + // XXX: TODO: should this function be `Value::new` instead? + let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_alloc_value(ctx.as_ptr(), self.as_ptr()) + })?; + + // Ok(Value::from((inner, self))) + todo!() } } diff --git a/nixide/src/expr/eval_state_builder.rs b/nixide/src/expr/evalstatebuilder.rs similarity index 93% rename from nixide/src/expr/eval_state_builder.rs rename to nixide/src/expr/evalstatebuilder.rs index de2672b..1c6d34c 100644 --- a/nixide/src/expr/eval_state_builder.rs +++ b/nixide/src/expr/evalstatebuilder.rs @@ -129,14 +129,13 @@ impl EvalStateBuilder { .map(|()| self); // ensure all allocated memory is dropped - // XXX: TODO!! - // unsafe { - // Vec::from_raw_parts(ptr, paths_len, paths_capacity) - // .into_iter() - // .map(|p| { - // _ = CString::from_raw(p as *mut c_char); - // }) - // }; + unsafe { + Vec::from_raw_parts(ptr, paths_len, paths_capacity) + .into_iter() + .map(|p| { + _ = CString::from_raw(p as *mut c_char); + }) + }; result } diff --git a/nixide/src/expr/mod.rs b/nixide/src/expr/mod.rs index 6865d5b..57f6808 100644 --- a/nixide/src/expr/mod.rs +++ b/nixide/src/expr/mod.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod tests; -mod eval_state; -mod eval_state_builder; +mod evalstate; +mod evalstatebuilder; mod realised_string; mod values; -pub use eval_state::EvalState; -pub use eval_state_builder::EvalStateBuilder; +pub use evalstate::EvalState; +pub use evalstatebuilder::EvalStateBuilder; pub use realised_string::RealisedString; pub use values::*; diff --git a/nixide/src/expr/value.rs b/nixide/src/expr/value.rs new file mode 100644 index 0000000..6d6bff8 --- /dev/null +++ b/nixide/src/expr/value.rs @@ -0,0 +1,237 @@ +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; +use std::ptr::NonNull; + +use super::{EvalState, ValueType}; +use crate::errors::{ErrorContext, NixideResult}; +use crate::sys; +use crate::util::wrappers::AsInnerPtr; +use crate::util::{panic_issue_call_failed, wrap}; + +pub use crate::expr::values::{ + NixAttrs, NixBool, NixExternal, NixFloat, NixFunction, NixInt, NixList, NixNull, NixPath, + NixString, NixThunk, NixValue, +}; + +/// A Nix value +/// +/// This represents any value in the Nix language, including primitives, +/// collections, and functions. +/// +/// ```cpp +/// pub const ValueType_NIX_TYPE_THUNK: ValueType = 0; +/// pub const ValueType_NIX_TYPE_INT: ValueType = 1; +/// pub const ValueType_NIX_TYPE_FLOAT: ValueType = 2; +/// pub const ValueType_NIX_TYPE_BOOL: ValueType = 3; +/// pub const ValueType_NIX_TYPE_STRING: ValueType = 4; +/// pub const ValueType_NIX_TYPE_PATH: ValueType = 5; +/// pub const ValueType_NIX_TYPE_NULL: ValueType = 6; +/// pub const ValueType_NIX_TYPE_ATTRS: ValueType = 7; +/// pub const ValueType_NIX_TYPE_LIST: ValueType = 8; +/// pub const ValueType_NIX_TYPE_FUNCTION: ValueType = 9; +/// pub const ValueType_NIX_TYPE_EXTERNAL: ValueType = 10; +/// ``` +pub enum Value { + /// Unevaluated expression + /// + /// Thunks often contain an expression and closure, but may contain other + /// representations too. + /// + /// Their state is mutable, unlike that of the other types. + Thunk(NixThunk), + Int(NixInt), + Float(NixFloat), + Bool(NixBool), + String(NixString), + Path(NixPath), + Null(NixNull), + Attrs(NixAttrs), + List(NixList), + Function(NixFunction), + External(NixExternal), +} + +impl Value { + /// Forces the evaluation of a Nix value. + /// + /// The Nix interpreter is lazy, and not-yet-evaluated values can be + /// of type NIX_TYPE_THUNK instead of their actual value. + /// + /// This function mutates such a `nix_value`, so that, if successful, it has its final type. + /// + /// @param[out] context Optional, stores error information + /// @param[in] state The state of the evaluation. + /// @param[in,out] value The Nix value to force. + /// @post value is not of type NIX_TYPE_THUNK + /// @return NIX_OK if the force operation was successful, an error code + /// otherwise. + pub fn force(&mut self) -> NixideResult<()> { + // XXX: TODO: move force and force_deep to the EvalState + wrap::nix_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_value_force(ctx.as_ptr(), self.state.as_ptr(), self.as_ptr()); + }) + } + + /// Force deep evaluation of this value. + /// + /// This forces evaluation of the value and all its nested components. + /// + /// # Errors + /// + /// Returns an error if evaluation fails. + pub fn force_deep(&mut self) -> NixideResult<()> { + // XXX: TODO: move force and force_deep to the EvalState + wrap::nix_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_value_force_deep(ctx.as_ptr(), self.state.as_ptr(), self.as_ptr()); + }) + } + + /// Get the type of this value. + #[must_use] + pub fn value_type(&self) -> ValueType { + // NOTE: an error here only occurs if `nix_get_type` catches an error, + // NOTE: which in turn only happens if the `sys::nix_value*` is a null pointer + // NOTE: or points to an uninitialised `nix_value` struct. + ValueType::from({ + wrap::nix_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_get_type(ctx.as_ptr(), self.as_ptr()) + }) + .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)) + }) + } + + // XXX: TODO: rewrite `expr/value.rs` to make this redundant + // fn expect_type(&self, expected: ValueType) -> NixideResult<()> { + // let got = self.value_type(); + // if got != expected { + // return Err(new_nixide_error!( + // InvalidType, + // expected.to_string(), + // got.to_string() + // )); + // } + // Ok(()) + // } + + /// Format this value as Nix syntax. + /// + /// This provides a string representation that matches Nix's own syntax, + /// making it useful for debugging and displaying values to users. + /// + /// # Errors + /// + /// Returns an error if the value cannot be converted to a string + /// representation. + pub fn to_nix_string(&self) -> NixideResult { + match self.value_type() { + | ValueType::Int => Ok(self.as_int()?.to_string()), + | ValueType::Float => Ok(self.as_float()?.to_string()), + | ValueType::Bool => Ok(if self.as_bool()? { + "true".to_string() + } else { + "false".to_string() + }), + | ValueType::String => Ok(format!("\"{}\"", self.as_string()?.replace('"', "\\\""))), + | ValueType::Null => Ok("null".to_string()), + | ValueType::Attrs => Ok("{ }".to_string()), + | ValueType::List => Ok("[ ]".to_string()), + | ValueType::Function => Ok("".to_string()), + | ValueType::Path => Ok("".to_string()), + | ValueType::Thunk => Ok("".to_string()), + | ValueType::External => Ok("".to_string()), + } + } +} + +impl Drop for Value { + fn drop(&mut self) { + let ctx = ErrorContext::new(); + unsafe { + sys::nix_value_decref(ctx.as_ptr(), self.as_ptr()); + } + } +} + +impl Display for Value { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + match self.value_type() { + | ValueType::Int => { + if let Ok(val) = self.as_int() { + write!(f, "{val}") + } else { + write!(f, "") + } + }, + | ValueType::Float => { + if let Ok(val) = self.as_float() { + write!(f, "{val}") + } else { + write!(f, "") + } + }, + | ValueType::Bool => { + if let Ok(val) = self.as_bool() { + write!(f, "{val}") + } else { + write!(f, "") + } + }, + | ValueType::String => { + if let Ok(val) = self.as_string() { + write!(f, "{val}") + } else { + write!(f, "") + } + }, + | ValueType::Null => write!(f, "null"), + | ValueType::Attrs => write!(f, "{{ }}"), + | ValueType::List => write!(f, "[ ]"), + | ValueType::Function => write!(f, ""), + | ValueType::Path => write!(f, ""), + | ValueType::Thunk => write!(f, ""), + | ValueType::External => write!(f, ""), + } + } +} + +impl Debug for Value { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let value_type = self.value_type(); + match value_type { + | ValueType::Int => { + if let Ok(val) = self.as_int() { + write!(f, "Value::Int({val})") + } else { + write!(f, "Value::Int()") + } + }, + | ValueType::Float => { + if let Ok(val) = self.as_float() { + write!(f, "Value::Float({val})") + } else { + write!(f, "Value::Float()") + } + }, + | ValueType::Bool => { + if let Ok(val) = self.as_bool() { + write!(f, "Value::Bool({val})") + } else { + write!(f, "Value::Bool()") + } + }, + | ValueType::String => { + if let Ok(val) = self.as_string() { + write!(f, "Value::String({val:?})") + } else { + write!(f, "Value::String()") + } + }, + | ValueType::Null => write!(f, "Value::Null"), + | ValueType::Attrs => write!(f, "Value::Attrs({{ }})"), + | ValueType::List => write!(f, "Value::List([ ])"), + | ValueType::Function => write!(f, "Value::Function()"), + | ValueType::Path => write!(f, "Value::Path()"), + | ValueType::Thunk => write!(f, "Value::Thunk()"), + | ValueType::External => write!(f, "Value::External()"), + } + } +} diff --git a/nixide/src/expr/values/attrs.rs b/nixide/src/expr/values/attrs.rs index 4baacd0..8008bf7 100644 --- a/nixide/src/expr/values/attrs.rs +++ b/nixide/src/expr/values/attrs.rs @@ -4,16 +4,16 @@ 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, - state: Rc>>, + state: Rc>, len: u32, } @@ -61,7 +61,7 @@ impl NixValue for NixAttrs { sys::ValueType_NIX_TYPE_ATTRS } - fn from(inner: NonNull, state: Rc>>) -> 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()) }) @@ -88,7 +88,7 @@ impl NixAttrs { sys::nix_get_attr_byidx( ctx.as_ptr(), self.as_ptr(), - self.state.borrow_mut().as_ptr(), + self.state.borrow().as_ptr(), index, name_ptr, ) @@ -115,7 +115,7 @@ impl NixAttrs { sys::nix_get_attr_byidx_lazy( ctx.as_ptr(), self.as_ptr(), - self.state.borrow_mut().as_ptr(), + self.state.borrow().as_ptr(), index, name_ptr, ) @@ -140,7 +140,7 @@ impl NixAttrs { sys::nix_get_attr_name_byidx( ctx.as_ptr(), self.as_ptr(), - self.state.borrow_mut().as_ptr(), + self.state.borrow().as_ptr(), index, ) }) @@ -161,7 +161,7 @@ impl NixAttrs { sys::nix_get_attr_byname( ctx.as_ptr(), self.as_ptr(), - self.state.borrow_mut().as_ptr(), + self.state.borrow().as_ptr(), name.as_ref() .into_c_ptr() .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)), @@ -187,7 +187,7 @@ impl NixAttrs { sys::nix_get_attr_byname_lazy( ctx.as_ptr(), self.as_ptr(), - self.state.borrow_mut().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 01f5718..d604c94 100644 --- a/nixide/src/expr/values/bool.rs +++ b/nixide/src/expr/values/bool.rs @@ -5,14 +5,14 @@ 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, - state: Rc>>, + state: Rc>, value: bool, } @@ -60,7 +60,7 @@ impl NixValue for NixBool { sys::ValueType_NIX_TYPE_BOOL } - fn from(inner: NonNull, state: Rc>>) -> 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()) }) diff --git a/nixide/src/expr/values/float.rs b/nixide/src/expr/values/float.rs index b47569b..1187821 100644 --- a/nixide/src/expr/values/float.rs +++ b/nixide/src/expr/values/float.rs @@ -5,13 +5,13 @@ use std::rc::Rc; use super::NixValue; use crate::errors::ErrorContext; -use crate::sys; use crate::util::wrappers::AsInnerPtr; use crate::util::{panic_issue_call_failed, wrap}; +use crate::{EvalState, sys}; pub struct NixFloat { inner: NonNull, - state: Rc>>, + state: Rc>, value: f64, } @@ -59,7 +59,7 @@ impl NixValue for NixFloat { sys::ValueType_NIX_TYPE_FLOAT } - fn from(inner: NonNull, state: Rc>>) -> 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()) }) diff --git a/nixide/src/expr/values/function.rs b/nixide/src/expr/values/function.rs index 98827b1..5cf15a2 100644 --- a/nixide/src/expr/values/function.rs +++ b/nixide/src/expr/values/function.rs @@ -3,16 +3,16 @@ use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::ptr::NonNull; use std::rc::Rc; -use super::{NixValue, Value}; +use super::{NixThunk, 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, - state: Rc>>, + state: Rc>, value: i64, } @@ -60,7 +60,7 @@ impl NixValue for NixFunction { sys::ValueType_NIX_TYPE_FUNCTION } - fn from(inner: NonNull, state: Rc>>) -> 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()) }) diff --git a/nixide/src/expr/values/int.rs b/nixide/src/expr/values/int.rs index 4ddd147..eccd7ef 100644 --- a/nixide/src/expr/values/int.rs +++ b/nixide/src/expr/values/int.rs @@ -5,13 +5,13 @@ use std::rc::Rc; use super::NixValue; use crate::errors::ErrorContext; -use crate::sys; use crate::util::wrappers::AsInnerPtr; use crate::util::{panic_issue_call_failed, wrap}; +use crate::{EvalState, sys}; pub struct NixInt { inner: NonNull, - state: Rc>>, + state: Rc>, value: i64, } @@ -59,7 +59,7 @@ impl NixValue for NixInt { sys::ValueType_NIX_TYPE_INT } - fn from(inner: NonNull, state: Rc>>) -> 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()) }) diff --git a/nixide/src/expr/values/list.rs b/nixide/src/expr/values/list.rs index fb82bc7..c062a87 100644 --- a/nixide/src/expr/values/list.rs +++ b/nixide/src/expr/values/list.rs @@ -5,13 +5,14 @@ use std::rc::Rc; use super::{NixThunk, NixValue, Value}; use crate::errors::ErrorContext; -use crate::sys; use crate::util::wrappers::AsInnerPtr; use crate::util::{panic_issue_call_failed, wrap}; +use crate::{EvalState, sys}; pub struct NixList { inner: NonNull, - state: Rc>>, + state: Rc>, + value: i64, } impl Drop for NixList { @@ -58,8 +59,17 @@ impl NixValue for NixList { sys::ValueType_NIX_TYPE_LIST } - fn from(inner: NonNull, state: Rc>>) -> Self { - Self { inner, state } + 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()) + }) + .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); + + Self { + inner, + state, + value, + } } } diff --git a/nixide/src/expr/values/mod.rs b/nixide/src/expr/values/mod.rs index 6b1f459..27fd5f6 100644 --- a/nixide/src/expr/values/mod.rs +++ b/nixide/src/expr/values/mod.rs @@ -45,7 +45,7 @@ pub trait NixValue: Drop + Display + Debug + AsInnerPtr { fn type_id(&self) -> sys::ValueType; /// TODO - fn from(inner: NonNull, state: Rc>>) -> Self; + fn from(inner: NonNull, state: Rc>) -> Self; } /// A Nix value @@ -111,18 +111,8 @@ pub enum Value { // Failed(NixFailed), } -impl - From<( - NonNull, - Rc>>, - )> for Value -{ - fn from( - value: ( - NonNull, - Rc>>, - ), - ) -> Self { +impl From<(NonNull, Rc>)> for Value { + fn from(value: (NonNull, Rc>)) -> Self { let (inner, state) = value; wrap::nix_fn!(|ctx: &ErrorContext| unsafe { @@ -135,7 +125,6 @@ impl }) .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); - #[allow(non_upper_case_globals)] match type_id { ValueType_NIX_TYPE_THUNK => Value::Thunk(::from(inner, state)), ValueType_NIX_TYPE_INT => Value::Int(::from(inner, state)), diff --git a/nixide/src/expr/values/null.rs b/nixide/src/expr/values/null.rs index 11440de..7b92254 100644 --- a/nixide/src/expr/values/null.rs +++ b/nixide/src/expr/values/null.rs @@ -5,12 +5,12 @@ use std::rc::Rc; use super::NixValue; use crate::errors::ErrorContext; -use crate::sys; use crate::util::wrappers::AsInnerPtr; +use crate::{EvalState, sys}; pub struct NixNull { inner: NonNull, - state: Rc>>, + state: Rc>, } impl Drop for NixNull { @@ -57,7 +57,7 @@ impl NixValue for NixNull { sys::ValueType_NIX_TYPE_NULL } - fn from(inner: NonNull, state: Rc>>) -> Self { + 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 b25dfa6..9a7fdb2 100644 --- a/nixide/src/expr/values/path.rs +++ b/nixide/src/expr/values/path.rs @@ -7,14 +7,14 @@ 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, - state: Rc>>, + state: Rc>, value: PathBuf, } @@ -62,7 +62,7 @@ impl NixValue for NixPath { sys::ValueType_NIX_TYPE_PATH } - fn from(inner: NonNull, state: Rc>>) -> 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()) }) diff --git a/nixide/src/expr/values/string.rs b/nixide/src/expr/values/string.rs index 93ec66d..9ee305a 100644 --- a/nixide/src/expr/values/string.rs +++ b/nixide/src/expr/values/string.rs @@ -6,14 +6,14 @@ 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, - state: Rc>>, + state: Rc>, value: String, } @@ -61,7 +61,7 @@ impl NixValue for NixString { sys::ValueType_NIX_TYPE_STRING } - fn from(inner: NonNull, state: Rc>>) -> 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( diff --git a/nixide/src/expr/values/thunk.rs b/nixide/src/expr/values/thunk.rs index 6327623..5fbe0f7 100644 --- a/nixide/src/expr/values/thunk.rs +++ b/nixide/src/expr/values/thunk.rs @@ -4,6 +4,7 @@ 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; @@ -11,7 +12,7 @@ use crate::util::{panic_issue_call_failed, wrap}; pub struct NixThunk { inner: NonNull, - state: Rc>>, + state: Rc>, } impl Drop for NixThunk { @@ -58,7 +59,7 @@ impl NixValue for NixThunk { sys::ValueType_NIX_TYPE_THUNK } - fn from(inner: NonNull, state: Rc>>) -> Self { + fn from(inner: NonNull, state: Rc>) -> Self { Self { inner, state } } } diff --git a/nixide/src/expr/valuetype.rs b/nixide/src/expr/valuetype.rs new file mode 100644 index 0000000..ad7b194 --- /dev/null +++ b/nixide/src/expr/valuetype.rs @@ -0,0 +1,68 @@ +use std::fmt::{Display, Formatter, Result as FmtResult}; + +use crate::sys; + +/// Nix value types. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ValueType { + /// Thunk (unevaluated expression). + Thunk, + /// Integer value. + Int, + /// Float value. + Float, + /// Boolean value. + Bool, + /// String value. + String, + /// Path value. + Path, + /// Null value. + Null, + /// Attribute set. + Attrs, + /// List. + List, + /// Function. + Function, + /// External value. + External, +} + +impl From for ValueType { + fn from(value_type: sys::ValueType) -> Self { + match value_type { + sys::ValueType_NIX_TYPE_THUNK => ValueType::Thunk, + sys::ValueType_NIX_TYPE_INT => ValueType::Int, + sys::ValueType_NIX_TYPE_FLOAT => ValueType::Float, + sys::ValueType_NIX_TYPE_BOOL => ValueType::Bool, + sys::ValueType_NIX_TYPE_STRING => ValueType::String, + sys::ValueType_NIX_TYPE_PATH => ValueType::Path, + sys::ValueType_NIX_TYPE_NULL => ValueType::Null, + sys::ValueType_NIX_TYPE_ATTRS => ValueType::Attrs, + sys::ValueType_NIX_TYPE_LIST => ValueType::List, + sys::ValueType_NIX_TYPE_FUNCTION => ValueType::Function, + sys::ValueType_NIX_TYPE_EXTERNAL => ValueType::External, + _ => unreachable!("call to `nixide::ValueType::from_c` failed: please open an issue on https://github.com/cry128/nixide"), + } + } +} + +impl Display for ValueType { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let name = match self { + ValueType::Thunk => "thunk", + ValueType::Int => "int", + ValueType::Float => "float", + ValueType::Bool => "bool", + ValueType::String => "string", + ValueType::Path => "path", + ValueType::Null => "null", + ValueType::Attrs => "attrs", + ValueType::List => "list", + ValueType::Function => "function", + ValueType::External => "external", + }; + write!(f, "{name}") + } +} diff --git a/nixide/src/lib.rs b/nixide/src/lib.rs index 027aec7..c4b7be6 100644 --- a/nixide/src/lib.rs +++ b/nixide/src/lib.rs @@ -81,7 +81,7 @@ fn init_libstore() { /// > that does not rely on Rust's stdlib services. /// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) #[ctor] -#[cfg(feature = "exprs")] +#[cfg(feature = "expr")] fn init_libexpr() { unsafe { INIT_LIBEXPR_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe {