implement NixValue types
This commit is contained in:
parent
84c51f5b16
commit
0d8468c71e
18 changed files with 981 additions and 107 deletions
|
|
@ -137,7 +137,9 @@ impl ErrorContext {
|
|||
pub fn new() -> Self {
|
||||
match NonNull::new(unsafe { sys::nix_c_context_create() }) {
|
||||
Some(inner) => ErrorContext { inner },
|
||||
None => panic!("[nixide] CRITICAL FAILURE: Out-Of-Memory condition reached - `sys::nix_c_context_create` allocation failed!"),
|
||||
None => panic!(
|
||||
"[nixide] CRITICAL FAILURE: Out-Of-Memory condition reached - `sys::nix_c_context_create` allocation failed!"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ 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::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{NixideResult, Store};
|
||||
|
||||
/// Nix evaluation state for evaluating expressions.
|
||||
|
|
@ -65,7 +65,11 @@ impl EvalState {
|
|||
let path_c = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?;
|
||||
|
||||
// Allocate value for result
|
||||
let value = self.new_value()?;
|
||||
// XXX: TODO: create a method for this (``)
|
||||
let value = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
// Evaluate expression
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
|
|
@ -78,6 +82,7 @@ impl EvalState {
|
|||
);
|
||||
value
|
||||
})
|
||||
.map(|ptr| Value::from((ptr, self)))
|
||||
}
|
||||
|
||||
/// Allocate a new value.
|
||||
|
|
@ -91,7 +96,7 @@ impl EvalState {
|
|||
sys::nix_alloc_value(ctx.as_ptr(), self.as_ptr())
|
||||
})?;
|
||||
|
||||
Ok(Value::new(inner, self))
|
||||
Ok(Value::from((inner, self)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use std::ffi::{c_char, CStr, CString};
|
||||
use std::ffi::{CString, c_char};
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::EvalState;
|
||||
use crate::Store;
|
||||
use crate::errors::{ErrorContext, NixideResult};
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::Store;
|
||||
|
||||
/// Builder for Nix evaluation state.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -4,13 +4,9 @@ mod tests;
|
|||
mod evalstate;
|
||||
mod evalstatebuilder;
|
||||
mod realised_string;
|
||||
mod value;
|
||||
mod values;
|
||||
mod valuetype;
|
||||
|
||||
pub use evalstate::EvalState;
|
||||
pub use evalstatebuilder::EvalStateBuilder;
|
||||
pub use realised_string::RealisedString;
|
||||
pub use value::Value;
|
||||
pub use values::{NixInt, NixValue};
|
||||
pub use valuetype::ValueType;
|
||||
pub use values::*;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ use crate::sys;
|
|||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
||||
pub use crate::expr::values::{NixBool, NixFloat, NixInt, NixString, NixValue};
|
||||
pub use crate::expr::values::{
|
||||
NixAttrs, NixBool, NixExternal, NixFloat, NixFunction, NixInt, NixList, NixNull, NixPath,
|
||||
NixString, NixThunk, NixValue,
|
||||
};
|
||||
|
||||
/// A Nix value
|
||||
///
|
||||
|
|
@ -28,31 +31,39 @@ pub use crate::expr::values::{NixBool, NixFloat, NixInt, NixString, NixValue};
|
|||
/// pub const ValueType_NIX_TYPE_EXTERNAL: ValueType = 10;
|
||||
/// ```
|
||||
pub enum Value {
|
||||
// Thunk(NixThunk),
|
||||
/// 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),
|
||||
Path(NixPath),
|
||||
Null(NixNull),
|
||||
Attrs(NixAttrs),
|
||||
List(NixList),
|
||||
Function(NixFunction),
|
||||
External(NixExternal),
|
||||
}
|
||||
|
||||
impl<'a> Value<'a> {
|
||||
pub(crate) fn new(inner: NonNull<sys::nix_value>, state: &'a EvalState) -> Self {
|
||||
Value { inner, state }
|
||||
}
|
||||
|
||||
/// Force evaluation of this value.
|
||||
impl Value {
|
||||
/// Forces the evaluation of a Nix value.
|
||||
///
|
||||
/// If the value is a thunk, this will evaluate it to its final form.
|
||||
/// The Nix interpreter is lazy, and not-yet-evaluated values can be
|
||||
/// of type NIX_TYPE_THUNK instead of their actual value.
|
||||
///
|
||||
/// # Errors
|
||||
/// This function mutates such a `nix_value`, so that, if successful, it has its final type.
|
||||
///
|
||||
/// Returns an error if evaluation fails.
|
||||
/// @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 {
|
||||
|
|
@ -112,21 +123,21 @@ impl<'a> Value<'a> {
|
|||
/// representation.
|
||||
pub fn to_nix_string(&self) -> NixideResult<String> {
|
||||
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()? {
|
||||
| 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("{ <attrs> }".to_string()),
|
||||
ValueType::List => Ok("[ <list> ]".to_string()),
|
||||
ValueType::Function => Ok("<function>".to_string()),
|
||||
ValueType::Path => Ok("<path>".to_string()),
|
||||
ValueType::Thunk => Ok("<thunk>".to_string()),
|
||||
ValueType::External => Ok("<external>".to_string()),
|
||||
| ValueType::String => Ok(format!("\"{}\"", self.as_string()?.replace('"', "\\\""))),
|
||||
| ValueType::Null => Ok("null".to_string()),
|
||||
| ValueType::Attrs => Ok("{ <attrs> }".to_string()),
|
||||
| ValueType::List => Ok("[ <list> ]".to_string()),
|
||||
| ValueType::Function => Ok("<function>".to_string()),
|
||||
| ValueType::Path => Ok("<path>".to_string()),
|
||||
| ValueType::Thunk => Ok("<thunk>".to_string()),
|
||||
| ValueType::External => Ok("<external>".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -143,41 +154,41 @@ impl Drop for Value {
|
|||
impl Display for Value {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
match self.value_type() {
|
||||
ValueType::Int => {
|
||||
| ValueType::Int => {
|
||||
if let Ok(val) = self.as_int() {
|
||||
write!(f, "{val}")
|
||||
} else {
|
||||
write!(f, "<int error>")
|
||||
}
|
||||
}
|
||||
ValueType::Float => {
|
||||
},
|
||||
| ValueType::Float => {
|
||||
if let Ok(val) = self.as_float() {
|
||||
write!(f, "{val}")
|
||||
} else {
|
||||
write!(f, "<float error>")
|
||||
}
|
||||
}
|
||||
ValueType::Bool => {
|
||||
},
|
||||
| ValueType::Bool => {
|
||||
if let Ok(val) = self.as_bool() {
|
||||
write!(f, "{val}")
|
||||
} else {
|
||||
write!(f, "<bool error>")
|
||||
}
|
||||
}
|
||||
ValueType::String => {
|
||||
},
|
||||
| ValueType::String => {
|
||||
if let Ok(val) = self.as_string() {
|
||||
write!(f, "{val}")
|
||||
} else {
|
||||
write!(f, "<string error>")
|
||||
}
|
||||
}
|
||||
ValueType::Null => write!(f, "null"),
|
||||
ValueType::Attrs => write!(f, "{{ <attrs> }}"),
|
||||
ValueType::List => write!(f, "[ <list> ]"),
|
||||
ValueType::Function => write!(f, "<function>"),
|
||||
ValueType::Path => write!(f, "<path>"),
|
||||
ValueType::Thunk => write!(f, "<thunk>"),
|
||||
ValueType::External => write!(f, "<external>"),
|
||||
},
|
||||
| ValueType::Null => write!(f, "null"),
|
||||
| ValueType::Attrs => write!(f, "{{ <attrs> }}"),
|
||||
| ValueType::List => write!(f, "[ <list> ]"),
|
||||
| ValueType::Function => write!(f, "<function>"),
|
||||
| ValueType::Path => write!(f, "<path>"),
|
||||
| ValueType::Thunk => write!(f, "<thunk>"),
|
||||
| ValueType::External => write!(f, "<external>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -186,41 +197,41 @@ impl Debug for Value {
|
|||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
let value_type = self.value_type();
|
||||
match value_type {
|
||||
ValueType::Int => {
|
||||
| ValueType::Int => {
|
||||
if let Ok(val) = self.as_int() {
|
||||
write!(f, "Value::Int({val})")
|
||||
} else {
|
||||
write!(f, "Value::Int(<error>)")
|
||||
}
|
||||
}
|
||||
ValueType::Float => {
|
||||
},
|
||||
| ValueType::Float => {
|
||||
if let Ok(val) = self.as_float() {
|
||||
write!(f, "Value::Float({val})")
|
||||
} else {
|
||||
write!(f, "Value::Float(<error>)")
|
||||
}
|
||||
}
|
||||
ValueType::Bool => {
|
||||
},
|
||||
| ValueType::Bool => {
|
||||
if let Ok(val) = self.as_bool() {
|
||||
write!(f, "Value::Bool({val})")
|
||||
} else {
|
||||
write!(f, "Value::Bool(<error>)")
|
||||
}
|
||||
}
|
||||
ValueType::String => {
|
||||
},
|
||||
| ValueType::String => {
|
||||
if let Ok(val) = self.as_string() {
|
||||
write!(f, "Value::String({val:?})")
|
||||
} else {
|
||||
write!(f, "Value::String(<error>)")
|
||||
}
|
||||
}
|
||||
ValueType::Null => write!(f, "Value::Null"),
|
||||
ValueType::Attrs => write!(f, "Value::Attrs({{ <attrs> }})"),
|
||||
ValueType::List => write!(f, "Value::List([ <list> ])"),
|
||||
ValueType::Function => write!(f, "Value::Function(<function>)"),
|
||||
ValueType::Path => write!(f, "Value::Path(<path>)"),
|
||||
ValueType::Thunk => write!(f, "Value::Thunk(<thunk>)"),
|
||||
ValueType::External => write!(f, "Value::External(<external>)"),
|
||||
},
|
||||
| ValueType::Null => write!(f, "Value::Null"),
|
||||
| ValueType::Attrs => write!(f, "Value::Attrs({{ <attrs> }})"),
|
||||
| ValueType::List => write!(f, "Value::List([ <list> ])"),
|
||||
| ValueType::Function => write!(f, "Value::Function(<function>)"),
|
||||
| ValueType::Path => write!(f, "Value::Path(<path>)"),
|
||||
| ValueType::Thunk => write!(f, "Value::Thunk(<thunk>)"),
|
||||
| ValueType::External => write!(f, "Value::External(<external>)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,207 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixThunk, NixValue, Value};
|
||||
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<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
len: u32,
|
||||
}
|
||||
|
||||
impl Drop for NixAttrs {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_value_decref(ctx.as_ptr(), self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NixAttrs {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "<attrs>")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NixAttrs {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "NixAttrs")
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_value> for NixAttrs {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_value {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_value {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_value {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixValue for NixAttrs {
|
||||
#[inline]
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_ATTRS
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
let len = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attrs_size(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Self { inner, state, len }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixAttrs {
|
||||
#[inline]
|
||||
pub fn len(&self) -> u32 {
|
||||
self.len
|
||||
}
|
||||
|
||||
pub fn get_idx(&self, index: u32) -> Option<(String, Value)> {
|
||||
if index >= self.len {
|
||||
return None;
|
||||
}
|
||||
|
||||
let name_ptr = ptr::null_mut();
|
||||
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
name_ptr,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let name = (unsafe { *name_ptr })
|
||||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let value = Value::from((inner, self.state.clone()));
|
||||
|
||||
Some((name, value))
|
||||
}
|
||||
|
||||
pub fn get_idx_lazy(&self, index: u32) -> Option<(String, NixThunk)> {
|
||||
if index >= self.len {
|
||||
return None;
|
||||
}
|
||||
|
||||
let name_ptr = ptr::null_mut();
|
||||
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_byidx_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
name_ptr,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let name = (unsafe { *name_ptr })
|
||||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let value = <NixThunk as NixValue>::from(inner, self.state.clone());
|
||||
|
||||
Some((name, value))
|
||||
}
|
||||
|
||||
pub fn get_name_idx(&self, index: u32) -> Option<String> {
|
||||
if index >= self.len {
|
||||
return None;
|
||||
}
|
||||
|
||||
let name_ptr = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_name_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let name = name_ptr
|
||||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Some(name)
|
||||
}
|
||||
|
||||
pub fn get<T>(&self, name: T) -> Option<Value>
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
let result = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_byname(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
)
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Some(Value::from((inner, self.state.clone()))),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
..
|
||||
}) => None,
|
||||
Err(err) => panic_issue_call_failed!("{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lazy<T>(&self, name: T) -> Option<NixThunk>
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
let result = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_byname_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
)
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Some(<NixThunk as NixValue>::from(inner, self.state.clone())),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
..
|
||||
}) => None,
|
||||
Err(err) => panic_issue_call_failed!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,18 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
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<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: bool,
|
||||
}
|
||||
|
||||
|
|
@ -53,11 +56,11 @@ impl AsInnerPtr<sys::nix_value> for NixBool {
|
|||
|
||||
impl NixValue for NixBool {
|
||||
#[inline]
|
||||
fn id(&self) -> sys::ValueType {
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_BOOL
|
||||
}
|
||||
|
||||
fn new(inner: NonNull<sys::nix_value>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_bool(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -65,7 +68,11 @@ impl NixValue for NixBool {
|
|||
panic_issue_call_failed!("`sys::nix_get_bool` failed for valid `NixBool` ({})", err)
|
||||
});
|
||||
|
||||
Self { inner, value }
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
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<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: f64,
|
||||
}
|
||||
|
||||
|
|
@ -52,11 +55,11 @@ impl AsInnerPtr<sys::nix_value> for NixFloat {
|
|||
|
||||
impl NixValue for NixFloat {
|
||||
#[inline]
|
||||
fn id(&self) -> sys::ValueType {
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_FLOAT
|
||||
}
|
||||
|
||||
fn new(inner: NonNull<sys::nix_value>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_float(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -64,7 +67,11 @@ impl NixValue for NixFloat {
|
|||
panic_issue_call_failed!("`sys::nix_get_float` failed for valid `NixFloat` ({})", err)
|
||||
});
|
||||
|
||||
Self { inner, value }
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixThunk, NixValue, Value};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::SliceExt;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixFunction {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: i64,
|
||||
}
|
||||
|
||||
impl Drop for NixFunction {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_value_decref(ctx.as_ptr(), self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NixFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "<function>")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NixFunction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "NixFunction")
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_value> for NixFunction {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_value {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_value {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_value {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixValue for NixFunction {
|
||||
#[inline]
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_FUNCTION
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl Fn<(Value,)> for NixFunction {
|
||||
// extern "rust-call" fn call(&self, args: (Value,)) -> Value {
|
||||
// args.0
|
||||
// }
|
||||
// }
|
||||
|
||||
impl NixFunction {
|
||||
fn call<T>(&self, arg: &T) -> Value
|
||||
where
|
||||
T: NixValue,
|
||||
{
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_call(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.as_ptr(),
|
||||
arg.as_ptr(),
|
||||
inner.as_ptr(),
|
||||
);
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, self.state.clone()))
|
||||
}
|
||||
|
||||
fn call_many<T>(&self, args: &[&T]) -> Value
|
||||
where
|
||||
T: NixValue,
|
||||
{
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_call_multi(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.as_ptr(),
|
||||
args.len(),
|
||||
args.into_c_array(),
|
||||
inner.as_ptr(),
|
||||
);
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, self.state.clone()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
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<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: i64,
|
||||
}
|
||||
|
||||
|
|
@ -52,19 +55,21 @@ impl AsInnerPtr<sys::nix_value> for NixInt {
|
|||
|
||||
impl NixValue for NixInt {
|
||||
#[inline]
|
||||
fn id(&self) -> sys::ValueType {
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_INT
|
||||
}
|
||||
|
||||
fn new(inner: NonNull<sys::nix_value>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> 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!("`sys::nix_get_int` failed for valid `NixInt` ({})", err)
|
||||
});
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Self { inner, value }
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixThunk, NixValue, Value};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixList {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: i64,
|
||||
}
|
||||
|
||||
impl Drop for NixList {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_value_decref(ctx.as_ptr(), self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NixList {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "<list>")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NixList {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "NixList")
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_value> for NixList {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_value {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_value {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_value {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixValue for NixList {
|
||||
#[inline]
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_LIST
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NixList {
|
||||
/// Forces the evaluation on all elements of the list.
|
||||
///
|
||||
fn as_vec(&self) -> Vec<Value> {
|
||||
// XXX: TODO: should I just return a LazyArray instead?
|
||||
let mut value = Vec::new();
|
||||
for i in 0..self.len() {
|
||||
value.push(self.get(i));
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
fn as_vec_lazy(&self) -> Vec<NixThunk> {
|
||||
// XXX: TODO: should I just return a LazyArray instead?
|
||||
let mut value = Vec::new();
|
||||
for i in 0..self.len() {
|
||||
value.push(self.get_lazy(i));
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
/// Get the length of a list. This function preserves
|
||||
/// laziness and does not evaluate the internal fields.
|
||||
///
|
||||
fn len(&self) -> u32 {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_list_size(ctx.as_ptr(), self.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err))
|
||||
}
|
||||
|
||||
fn get(&self, index: u32) -> Value {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_list_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, self.state.clone()))
|
||||
}
|
||||
|
||||
fn get_lazy(&self, index: u32) -> NixThunk {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_list_byidx_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
<NixThunk as NixValue>::from(inner, self.state.clone())
|
||||
}
|
||||
}
|
||||
|
|
@ -10,21 +10,145 @@ mod path;
|
|||
mod string;
|
||||
mod thunk;
|
||||
|
||||
pub use attrs::NixAttrs;
|
||||
pub use bool::NixBool;
|
||||
pub use external::NixExternal;
|
||||
// pub use failed::NixFailed; // only in latest nix version
|
||||
pub use float::NixFloat;
|
||||
pub use function::NixFunction;
|
||||
pub use int::NixInt;
|
||||
pub use list::NixList;
|
||||
pub use null::NixNull;
|
||||
pub use path::NixPath;
|
||||
pub use string::NixString;
|
||||
pub use thunk::NixThunk;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::sys::{
|
||||
ValueType_NIX_TYPE_ATTRS, ValueType_NIX_TYPE_BOOL, ValueType_NIX_TYPE_EXTERNAL,
|
||||
ValueType_NIX_TYPE_FLOAT, ValueType_NIX_TYPE_FUNCTION, ValueType_NIX_TYPE_INT,
|
||||
ValueType_NIX_TYPE_LIST, ValueType_NIX_TYPE_NULL, ValueType_NIX_TYPE_PATH,
|
||||
ValueType_NIX_TYPE_STRING, ValueType_NIX_TYPE_THUNK,
|
||||
};
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
||||
pub trait NixValue: Drop + Display + Debug + AsInnerPtr<sys::nix_value> {
|
||||
/// TODO
|
||||
fn id(&self) -> sys::ValueType;
|
||||
fn type_id(&self) -> sys::ValueType;
|
||||
|
||||
/// TODO
|
||||
fn new(inner: NonNull<sys::nix_value>) -> Self;
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self;
|
||||
}
|
||||
|
||||
/// A Nix value
|
||||
///
|
||||
/// This represents any value in the Nix language, including primitives,
|
||||
/// collections, and functions.
|
||||
///
|
||||
/// # Nix C++ API Internals
|
||||
///
|
||||
/// ```cpp
|
||||
/// typedef enum {
|
||||
/// NIX_TYPE_THUNK = 0,
|
||||
/// NIX_TYPE_INT = 1,
|
||||
/// NIX_TYPE_FLOAT = 2,
|
||||
/// NIX_TYPE_BOOL = 3,
|
||||
/// NIX_TYPE_STRING = 4,
|
||||
/// NIX_TYPE_PATH = 5,
|
||||
/// NIX_TYPE_NULL = 6,
|
||||
/// NIX_TYPE_ATTRS = 7,
|
||||
/// NIX_TYPE_LIST = 8,
|
||||
/// NIX_TYPE_FUNCTION = 9,
|
||||
/// NIX_TYPE_EXTERNAL = 10,
|
||||
/// NIX_TYPE_FAILED = 11,
|
||||
///} ValueType;
|
||||
/// ```
|
||||
///
|
||||
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),
|
||||
|
||||
/// TODO
|
||||
Int(NixInt),
|
||||
|
||||
/// TODO
|
||||
Float(NixFloat),
|
||||
|
||||
/// TODO
|
||||
Bool(NixBool),
|
||||
|
||||
/// TODO
|
||||
String(NixString),
|
||||
|
||||
/// TODO
|
||||
Path(NixPath),
|
||||
|
||||
/// TODO
|
||||
Null(NixNull),
|
||||
|
||||
/// TODO
|
||||
Attrs(NixAttrs),
|
||||
|
||||
/// TODO
|
||||
List(NixList),
|
||||
|
||||
/// TODO
|
||||
Function(NixFunction),
|
||||
|
||||
/// TODO
|
||||
External(NixExternal),
|
||||
|
||||
/// TODO
|
||||
Failed(NixFailed),
|
||||
}
|
||||
|
||||
impl From<(NonNull<sys::nix_value>, Rc<RefCell<EvalState>>)> for Value {
|
||||
fn from(value: (NonNull<sys::nix_value>, Rc<RefCell<EvalState>>)) -> Self {
|
||||
let (inner, state) = value;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_force(ctx.as_ptr(), state.borrow().as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let type_id = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_type(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
match type_id {
|
||||
ValueType_NIX_TYPE_THUNK => Value::Thunk(<NixThunk as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_INT => Value::Int(<NixInt as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_FLOAT => Value::Float(<NixFloat as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_BOOL => Value::Bool(<NixBool as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_STRING => Value::String(<NixString as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_PATH => Value::Path(<NixPath as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_NULL => Value::Null(<NixNull as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_ATTRS => Value::Attrs(<NixAttrs as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_LIST => Value::List(<NixList as NixValue>::from(inner, state)),
|
||||
ValueType_NIX_TYPE_FUNCTION => {
|
||||
Value::Function(<NixFunction as NixValue>::from(inner, state))
|
||||
},
|
||||
ValueType_NIX_TYPE_EXTERNAL => {
|
||||
Value::External(<NixExternal as NixValue>::from(inner, state))
|
||||
},
|
||||
// | sys::ValueType_NIX_TYPE_FAILED => {
|
||||
// Value::Failed(<NixFailed as NixValue>::from(inner, state))
|
||||
// },
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixNull {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
}
|
||||
|
||||
impl Drop for NixNull {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_value_decref(ctx.as_ptr(), self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NixNull {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "null")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NixNull {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "NixNull")
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_value> for NixNull {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_value {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_value {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_value {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixValue for NixNull {
|
||||
#[inline]
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_NULL
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
Self { inner, state }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::CCharPtrExt;
|
||||
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<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: PathBuf,
|
||||
}
|
||||
|
||||
impl Drop for NixPath {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_value_decref(ctx.as_ptr(), self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NixPath {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "<path>")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NixPath {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "NixPath(\"${}\")", self.value().display())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_value> for NixPath {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_value {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_value {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_value {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixValue for NixPath {
|
||||
#[inline]
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_PATH
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_path_string(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.and_then(CCharPtrExt::to_utf8_string)
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NixPath {
|
||||
/// Returns a shared reference to the underlying value.
|
||||
///
|
||||
#[inline]
|
||||
fn value(&self) -> &PathBuf {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
use std::cell::LazyCell;
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::expr::RealisedString;
|
||||
use crate::util::panic_issue_call_failed;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{sys, NixideResult};
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixString {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
value: String,
|
||||
}
|
||||
|
||||
|
|
@ -55,23 +57,28 @@ impl AsInnerPtr<sys::nix_value> for NixString {
|
|||
|
||||
impl NixValue for NixString {
|
||||
#[inline]
|
||||
fn id(&self) -> sys::ValueType {
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_STRING
|
||||
}
|
||||
|
||||
fn new(inner: NonNull<sys::nix_value>) -> Self {
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_get_int(ctx.as_ptr(), inner.as_ptr())
|
||||
// })
|
||||
// .unwrap_or_else(|err| {
|
||||
// panic_issue_call_failed!(
|
||||
// "`sys::nix_get_int` failed for valid `NixString` ({})",
|
||||
// err
|
||||
// )
|
||||
// })
|
||||
// };
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
let value = wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_string(
|
||||
ctx.as_ptr(),
|
||||
inner.as_ptr(),
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
);
|
||||
}
|
||||
)
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Self { inner, value }
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
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;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
||||
pub struct NixThunk {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<EvalState>>,
|
||||
}
|
||||
|
||||
impl Drop for NixThunk {
|
||||
fn drop(&mut self) {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_decref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NixThunk {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "<thunk>")
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NixThunk {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "NixThunk")
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_value> for NixThunk {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_value {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_value {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_value {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixValue for NixThunk {
|
||||
#[inline]
|
||||
fn type_id(&self) -> sys::ValueType {
|
||||
sys::ValueType_NIX_TYPE_THUNK
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self {
|
||||
Self { inner, state }
|
||||
}
|
||||
}
|
||||
|
||||
impl NixThunk {
|
||||
fn to_inner(self) -> NonNull<sys::nix_value> {
|
||||
self.inner
|
||||
}
|
||||
|
||||
fn eval(self) -> Value {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_force(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.inner.as_ptr(),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((self.inner, self.state.to_owned()))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
// #![warn(missing_docs)]
|
||||
|
||||
#![cfg_attr(nightly, feature(fn_traits))]
|
||||
|
||||
pub extern crate libc;
|
||||
pub extern crate nixide_sys as sys;
|
||||
|
||||
|
|
@ -17,11 +19,11 @@ mod flake;
|
|||
mod store;
|
||||
|
||||
pub use errors::{NixError, NixideError, NixideResult};
|
||||
pub use verbosity::{set_verbosity, NixVerbosity};
|
||||
pub use verbosity::{NixVerbosity, set_verbosity};
|
||||
pub use version::NixVersion;
|
||||
|
||||
#[cfg(feature = "expr")]
|
||||
pub use expr::{EvalState, EvalStateBuilder, Value, ValueType};
|
||||
pub use expr::{EvalState, EvalStateBuilder, Value};
|
||||
#[cfg(feature = "store")]
|
||||
pub use store::{Store, StorePath};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ macro_rules! panic_issue {
|
|||
|
||||
macro_rules! panic_issue_call_failed {
|
||||
() => {{
|
||||
crate::util::panic_issue!("[nixide] call to `{}` failed", $crate::stdext::debug_name!())
|
||||
crate::util::panic_issue!("[nixide] call to `{}` failed", ::stdext::debug_name!())
|
||||
}};
|
||||
($($arg:expr),*) => {{
|
||||
crate::util::panic_issue!("[nixide] call to `{}` failed with \"{}\"", $crate::stdext::debug_name!(), format!($($arg),*))
|
||||
crate::util::panic_issue!("[nixide] call to `{}` failed with \"{}\"", ::stdext::debug_name!(), format!($($arg),*))
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue