Compare commits

..

No commits in common. "0d8468c71e7c79cdaadbae26989cb4015fe41954" and "bea4c09c744bf14d66303e5c7faccb48f23ff340" have entirely different histories.

27 changed files with 128 additions and 1059 deletions

3
.gitignore vendored
View file

@ -7,6 +7,3 @@
# Helix # Helix
/.helix /.helix
# Other
/notes

View file

@ -5,7 +5,10 @@ version = "0.1.0"
readme = "../README.md" readme = "../README.md"
license = "GPL-3.0" license = "GPL-3.0"
repository = "https://codeberg.org/luminary/nixide" repository = "https://codeberg.org/luminary/nixide"
authors = [ "_cry64 <them@dobutterfliescry.net>" ] authors = [
"_cry64 <them@dobutterfliescry.net>",
"foxxyora <foxxyora@noreply.codeberg.org>"
]
edition = "2024" edition = "2024"
build = "build.rs" build = "build.rs"

View file

@ -11,21 +11,21 @@ impl ParseCallbacks for DoxygenCallbacks {
match doxygen_bindgen::transform(comment) { match doxygen_bindgen::transform(comment) {
Ok(res) => Some(res), Ok(res) => Some(res),
Err(err) => { Err(err) => {
println!("cargo::warning=Problem processing doxygen comment: {comment}\n{err}"); println!("cargo:warning=Problem processing doxygen comment: {comment}\n{err}");
None None
}, }
} }
} }
} }
fn main() { fn main() {
// Invalidate the built crate whenever the wrapper changes // Invalidate the built crate whenever the wrapper changes
println!("cargo::rerun-if-changed=include/nix-util.h"); println!("cargo:rerun-if-changed=include/nix-util.h");
println!("cargo::rerun-if-changed=include/nix-store.h"); println!("cargo:rerun-if-changed=include/nix-store.h");
println!("cargo::rerun-if-changed=include/nix-expr.h"); println!("cargo:rerun-if-changed=include/nix-expr.h");
println!("cargo::rerun-if-changed=include/nix-fetchers.h"); println!("cargo:rerun-if-changed=include/nix-fetchers.h");
println!("cargo::rerun-if-changed=include/nix-flake.h"); println!("cargo:rerun-if-changed=include/nix-flake.h");
println!("cargo::rerun-if-changed=include/nix-main.h"); println!("cargo:rerun-if-changed=include/nix-main.h");
let libs = [ let libs = [
#[cfg(feature = "nix-util-c")] #[cfg(feature = "nix-util-c")]
@ -49,7 +49,7 @@ fn main() {
.expect(&format!("Unable to find .pc file for {}", name)); .expect(&format!("Unable to find .pc file for {}", name));
for p in lib.link_files { for p in lib.link_files {
println!("cargo::rustc-link-lib={}", p.display()); println!("cargo:rustc-link-lib={}", p.display());
} }
lib.include_paths lib.include_paths

View file

@ -5,9 +5,11 @@ version = "0.1.0"
readme = "../README.md" readme = "../README.md"
license = "GPL-3.0" license = "GPL-3.0"
repository = "https://codeberg.org/luminary/nixide" repository = "https://codeberg.org/luminary/nixide"
authors = [ "_cry64 <them@dobutterfliescry.net>" ] authors = [
"_cry64 <them@dobutterfliescry.net>",
"foxxyora <foxxyora@noreply.codeberg.org>",
]
edition = "2024" edition = "2024"
build = "build.rs"
[lib] [lib]
path = "src/lib.rs" path = "src/lib.rs"

View file

@ -1,15 +0,0 @@
use std::env;
fn main() {
// allow the `cfg(nightly)` attribute
println!("cargo::rustc-check-cfg=cfg(nightly)");
// NOTE: This allows nixide to conditionally compile based
// NOTE: whether a user has access to nightly features.
if let Ok(toolchain) = env::var("RUSTUP_TOOLCHAIN")
&& toolchain.contains("nightly")
{
// enable the `nightly` flag
println!("cargo::rustc-cfg=nightly");
}
}

View file

@ -137,9 +137,7 @@ impl ErrorContext {
pub fn new() -> Self { pub fn new() -> Self {
match NonNull::new(unsafe { sys::nix_c_context_create() }) { match NonNull::new(unsafe { sys::nix_c_context_create() }) {
Some(inner) => ErrorContext { inner }, Some(inner) => ErrorContext { inner },
None => panic!( None => panic!("[nixide] CRITICAL FAILURE: Out-Of-Memory condition reached - `sys::nix_c_context_create` allocation failed!"),
"[nixide] CRITICAL FAILURE: Out-Of-Memory condition reached - `sys::nix_c_context_create` allocation failed!"
),
} }
} }

View file

@ -4,11 +4,11 @@ use std::sync::Arc;
use crate::errors::new_nixide_error; use crate::errors::new_nixide_error;
use super::{NixValue, Value}; use super::Value;
use crate::errors::ErrorContext; use crate::errors::ErrorContext;
use crate::sys; use crate::sys;
use crate::util::wrap;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::util::{panic_issue_call_failed, wrap};
use crate::{NixideResult, Store}; use crate::{NixideResult, Store};
/// Nix evaluation state for evaluating expressions. /// Nix evaluation state for evaluating expressions.
@ -65,11 +65,7 @@ impl EvalState {
let path_c = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?; let path_c = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?;
// Allocate value for result // Allocate value for result
// XXX: TODO: create a method for this (``) let value = self.new_value()?;
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 // Evaluate expression
wrap::nix_fn!(|ctx: &ErrorContext| unsafe { wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
@ -82,7 +78,6 @@ impl EvalState {
); );
value value
}) })
.map(|ptr| Value::from((ptr, self)))
} }
/// Allocate a new value. /// Allocate a new value.
@ -96,7 +91,7 @@ impl EvalState {
sys::nix_alloc_value(ctx.as_ptr(), self.as_ptr()) sys::nix_alloc_value(ctx.as_ptr(), self.as_ptr())
})?; })?;
Ok(Value::from((inner, self))) Ok(Value::new(inner, self))
} }
} }

View file

@ -1,13 +1,13 @@
use std::ffi::{CString, c_char}; use std::ffi::{c_char, CStr, CString};
use std::ptr::{self, NonNull}; use std::ptr::{self, NonNull};
use std::sync::Arc; use std::sync::Arc;
use super::EvalState; use super::EvalState;
use crate::Store;
use crate::errors::{ErrorContext, NixideResult}; use crate::errors::{ErrorContext, NixideResult};
use crate::sys; use crate::sys;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::util::{panic_issue_call_failed, wrap}; use crate::util::{panic_issue_call_failed, wrap};
use crate::Store;
/// Builder for Nix evaluation state. /// Builder for Nix evaluation state.
/// ///

View file

@ -4,9 +4,13 @@ mod tests;
mod evalstate; mod evalstate;
mod evalstatebuilder; mod evalstatebuilder;
mod realised_string; mod realised_string;
mod value;
mod values; mod values;
mod valuetype;
pub use evalstate::EvalState; pub use evalstate::EvalState;
pub use evalstatebuilder::EvalStateBuilder; pub use evalstatebuilder::EvalStateBuilder;
pub use realised_string::RealisedString; pub use realised_string::RealisedString;
pub use values::*; pub use value::Value;
pub use values::{NixInt, NixValue};
pub use valuetype::ValueType;

View file

@ -7,10 +7,7 @@ use crate::sys;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::util::{panic_issue_call_failed, wrap}; use crate::util::{panic_issue_call_failed, wrap};
pub use crate::expr::values::{ pub use crate::expr::values::{NixBool, NixFloat, NixInt, NixString, NixValue};
NixAttrs, NixBool, NixExternal, NixFloat, NixFunction, NixInt, NixList, NixNull, NixPath,
NixString, NixThunk, NixValue,
};
/// A Nix value /// A Nix value
/// ///
@ -31,39 +28,31 @@ pub use crate::expr::values::{
/// pub const ValueType_NIX_TYPE_EXTERNAL: ValueType = 10; /// pub const ValueType_NIX_TYPE_EXTERNAL: ValueType = 10;
/// ``` /// ```
pub enum Value { pub enum Value {
/// Unevaluated expression // Thunk(NixThunk),
///
/// 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), Int(NixInt),
Float(NixFloat), Float(NixFloat),
Bool(NixBool), Bool(NixBool),
String(NixString), String(NixString),
Path(NixPath), // Path(NixPath),
Null(NixNull), // Null(NixNull),
Attrs(NixAttrs), // Attrs(NixAttrs),
List(NixList), // List(NixList),
Function(NixFunction), // Function(NixFunction),
External(NixExternal), // External(NixExternal),
} }
impl Value { impl<'a> Value<'a> {
/// Forces the evaluation of a Nix value. pub(crate) fn new(inner: NonNull<sys::nix_value>, state: &'a EvalState) -> Self {
Value { inner, state }
}
/// Force evaluation of this value.
/// ///
/// The Nix interpreter is lazy, and not-yet-evaluated values can be /// If the value is a thunk, this will evaluate it to its final form.
/// 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. /// # Errors
/// ///
/// @param[out] context Optional, stores error information /// Returns an error if evaluation fails.
/// @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<()> { pub fn force(&mut self) -> NixideResult<()> {
// XXX: TODO: move force and force_deep to the EvalState // XXX: TODO: move force and force_deep to the EvalState
wrap::nix_fn!(|ctx: &ErrorContext| unsafe { wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
@ -123,21 +112,21 @@ impl Value {
/// representation. /// representation.
pub fn to_nix_string(&self) -> NixideResult<String> { pub fn to_nix_string(&self) -> NixideResult<String> {
match self.value_type() { match self.value_type() {
| ValueType::Int => Ok(self.as_int()?.to_string()), ValueType::Int => Ok(self.as_int()?.to_string()),
| ValueType::Float => Ok(self.as_float()?.to_string()), ValueType::Float => Ok(self.as_float()?.to_string()),
| ValueType::Bool => Ok(if self.as_bool()? { ValueType::Bool => Ok(if self.as_bool()? {
"true".to_string() "true".to_string()
} else { } else {
"false".to_string() "false".to_string()
}), }),
| ValueType::String => Ok(format!("\"{}\"", self.as_string()?.replace('"', "\\\""))), ValueType::String => Ok(format!("\"{}\"", self.as_string()?.replace('"', "\\\""))),
| ValueType::Null => Ok("null".to_string()), ValueType::Null => Ok("null".to_string()),
| ValueType::Attrs => Ok("{ <attrs> }".to_string()), ValueType::Attrs => Ok("{ <attrs> }".to_string()),
| ValueType::List => Ok("[ <list> ]".to_string()), ValueType::List => Ok("[ <list> ]".to_string()),
| ValueType::Function => Ok("<function>".to_string()), ValueType::Function => Ok("<function>".to_string()),
| ValueType::Path => Ok("<path>".to_string()), ValueType::Path => Ok("<path>".to_string()),
| ValueType::Thunk => Ok("<thunk>".to_string()), ValueType::Thunk => Ok("<thunk>".to_string()),
| ValueType::External => Ok("<external>".to_string()), ValueType::External => Ok("<external>".to_string()),
} }
} }
} }
@ -154,41 +143,41 @@ impl Drop for Value {
impl Display for Value { impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.value_type() { match self.value_type() {
| ValueType::Int => { ValueType::Int => {
if let Ok(val) = self.as_int() { if let Ok(val) = self.as_int() {
write!(f, "{val}") write!(f, "{val}")
} else { } else {
write!(f, "<int error>") write!(f, "<int error>")
} }
}, }
| ValueType::Float => { ValueType::Float => {
if let Ok(val) = self.as_float() { if let Ok(val) = self.as_float() {
write!(f, "{val}") write!(f, "{val}")
} else { } else {
write!(f, "<float error>") write!(f, "<float error>")
} }
}, }
| ValueType::Bool => { ValueType::Bool => {
if let Ok(val) = self.as_bool() { if let Ok(val) = self.as_bool() {
write!(f, "{val}") write!(f, "{val}")
} else { } else {
write!(f, "<bool error>") write!(f, "<bool error>")
} }
}, }
| ValueType::String => { ValueType::String => {
if let Ok(val) = self.as_string() { if let Ok(val) = self.as_string() {
write!(f, "{val}") write!(f, "{val}")
} else { } else {
write!(f, "<string error>") write!(f, "<string error>")
} }
}, }
| ValueType::Null => write!(f, "null"), ValueType::Null => write!(f, "null"),
| ValueType::Attrs => write!(f, "{{ <attrs> }}"), ValueType::Attrs => write!(f, "{{ <attrs> }}"),
| ValueType::List => write!(f, "[ <list> ]"), ValueType::List => write!(f, "[ <list> ]"),
| ValueType::Function => write!(f, "<function>"), ValueType::Function => write!(f, "<function>"),
| ValueType::Path => write!(f, "<path>"), ValueType::Path => write!(f, "<path>"),
| ValueType::Thunk => write!(f, "<thunk>"), ValueType::Thunk => write!(f, "<thunk>"),
| ValueType::External => write!(f, "<external>"), ValueType::External => write!(f, "<external>"),
} }
} }
} }
@ -197,41 +186,41 @@ impl Debug for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let value_type = self.value_type(); let value_type = self.value_type();
match value_type { match value_type {
| ValueType::Int => { ValueType::Int => {
if let Ok(val) = self.as_int() { if let Ok(val) = self.as_int() {
write!(f, "Value::Int({val})") write!(f, "Value::Int({val})")
} else { } else {
write!(f, "Value::Int(<error>)") write!(f, "Value::Int(<error>)")
} }
}, }
| ValueType::Float => { ValueType::Float => {
if let Ok(val) = self.as_float() { if let Ok(val) = self.as_float() {
write!(f, "Value::Float({val})") write!(f, "Value::Float({val})")
} else { } else {
write!(f, "Value::Float(<error>)") write!(f, "Value::Float(<error>)")
} }
}, }
| ValueType::Bool => { ValueType::Bool => {
if let Ok(val) = self.as_bool() { if let Ok(val) = self.as_bool() {
write!(f, "Value::Bool({val})") write!(f, "Value::Bool({val})")
} else { } else {
write!(f, "Value::Bool(<error>)") write!(f, "Value::Bool(<error>)")
} }
}, }
| ValueType::String => { ValueType::String => {
if let Ok(val) = self.as_string() { if let Ok(val) = self.as_string() {
write!(f, "Value::String({val:?})") write!(f, "Value::String({val:?})")
} else { } else {
write!(f, "Value::String(<error>)") write!(f, "Value::String(<error>)")
} }
}, }
| ValueType::Null => write!(f, "Value::Null"), ValueType::Null => write!(f, "Value::Null"),
| ValueType::Attrs => write!(f, "Value::Attrs({{ <attrs> }})"), ValueType::Attrs => write!(f, "Value::Attrs({{ <attrs> }})"),
| ValueType::List => write!(f, "Value::List([ <list> ])"), ValueType::List => write!(f, "Value::List([ <list> ])"),
| ValueType::Function => write!(f, "Value::Function(<function>)"), ValueType::Function => write!(f, "Value::Function(<function>)"),
| ValueType::Path => write!(f, "Value::Path(<path>)"), ValueType::Path => write!(f, "Value::Path(<path>)"),
| ValueType::Thunk => write!(f, "Value::Thunk(<thunk>)"), ValueType::Thunk => write!(f, "Value::Thunk(<thunk>)"),
| ValueType::External => write!(f, "Value::External(<external>)"), ValueType::External => write!(f, "Value::External(<external>)"),
} }
} }
} }

View file

@ -1,207 +0,0 @@
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),
}
}
}

View file

@ -1,18 +1,15 @@
use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc;
use super::NixValue; use super::NixValue;
use crate::errors::ErrorContext; use crate::errors::ErrorContext;
use crate::sys;
use crate::util::panic_issue_call_failed; use crate::util::panic_issue_call_failed;
use crate::util::wrap; use crate::util::wrap;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::{EvalState, sys};
pub struct NixBool { pub struct NixBool {
inner: NonNull<sys::nix_value>, inner: NonNull<sys::nix_value>,
state: Rc<RefCell<EvalState>>,
value: bool, value: bool,
} }
@ -56,11 +53,11 @@ impl AsInnerPtr<sys::nix_value> for NixBool {
impl NixValue for NixBool { impl NixValue for NixBool {
#[inline] #[inline]
fn type_id(&self) -> sys::ValueType { fn id(&self) -> sys::ValueType {
sys::ValueType_NIX_TYPE_BOOL sys::ValueType_NIX_TYPE_BOOL
} }
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self { fn new(inner: NonNull<sys::nix_value>) -> Self {
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
sys::nix_get_bool(ctx.as_ptr(), inner.as_ptr()) sys::nix_get_bool(ctx.as_ptr(), inner.as_ptr())
}) })
@ -68,11 +65,7 @@ impl NixValue for NixBool {
panic_issue_call_failed!("`sys::nix_get_bool` failed for valid `NixBool` ({})", err) panic_issue_call_failed!("`sys::nix_get_bool` failed for valid `NixBool` ({})", err)
}); });
Self { Self { inner, value }
inner,
state,
value,
}
} }
} }

View file

@ -1,17 +1,14 @@
use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc;
use super::NixValue; use super::NixValue;
use crate::errors::ErrorContext; use crate::errors::ErrorContext;
use crate::sys;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::util::{panic_issue_call_failed, wrap}; use crate::util::{panic_issue_call_failed, wrap};
use crate::{EvalState, sys};
pub struct NixFloat { pub struct NixFloat {
inner: NonNull<sys::nix_value>, inner: NonNull<sys::nix_value>,
state: Rc<RefCell<EvalState>>,
value: f64, value: f64,
} }
@ -55,11 +52,11 @@ impl AsInnerPtr<sys::nix_value> for NixFloat {
impl NixValue for NixFloat { impl NixValue for NixFloat {
#[inline] #[inline]
fn type_id(&self) -> sys::ValueType { fn id(&self) -> sys::ValueType {
sys::ValueType_NIX_TYPE_FLOAT sys::ValueType_NIX_TYPE_FLOAT
} }
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self { fn new(inner: NonNull<sys::nix_value>) -> Self {
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
sys::nix_get_float(ctx.as_ptr(), inner.as_ptr()) sys::nix_get_float(ctx.as_ptr(), inner.as_ptr())
}) })
@ -67,11 +64,7 @@ impl NixValue for NixFloat {
panic_issue_call_failed!("`sys::nix_get_float` failed for valid `NixFloat` ({})", err) panic_issue_call_failed!("`sys::nix_get_float` failed for valid `NixFloat` ({})", err)
}); });
Self { Self { inner, value }
inner,
state,
value,
}
} }
} }

View file

@ -1,130 +0,0 @@
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()))
}
}

View file

@ -1,17 +1,14 @@
use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc;
use super::NixValue; use super::NixValue;
use crate::errors::ErrorContext; use crate::errors::ErrorContext;
use crate::sys;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::util::{panic_issue_call_failed, wrap}; use crate::util::{panic_issue_call_failed, wrap};
use crate::{EvalState, sys};
pub struct NixInt { pub struct NixInt {
inner: NonNull<sys::nix_value>, inner: NonNull<sys::nix_value>,
state: Rc<RefCell<EvalState>>,
value: i64, value: i64,
} }
@ -55,21 +52,19 @@ impl AsInnerPtr<sys::nix_value> for NixInt {
impl NixValue for NixInt { impl NixValue for NixInt {
#[inline] #[inline]
fn type_id(&self) -> sys::ValueType { fn id(&self) -> sys::ValueType {
sys::ValueType_NIX_TYPE_INT sys::ValueType_NIX_TYPE_INT
} }
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self { fn new(inner: NonNull<sys::nix_value>) -> Self {
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe { let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
sys::nix_get_int(ctx.as_ptr(), inner.as_ptr()) sys::nix_get_int(ctx.as_ptr(), inner.as_ptr())
}) })
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)); .unwrap_or_else(|err| {
panic_issue_call_failed!("`sys::nix_get_int` failed for valid `NixInt` ({})", err)
});
Self { Self { inner, value }
inner,
state,
value,
}
} }
} }

View file

@ -1,136 +0,0 @@
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())
}
}

View file

@ -10,145 +10,21 @@ mod path;
mod string; mod string;
mod thunk; mod thunk;
pub use attrs::NixAttrs;
pub use bool::NixBool; pub use bool::NixBool;
pub use external::NixExternal;
// pub use failed::NixFailed; // only in latest nix version
pub use float::NixFloat; pub use float::NixFloat;
pub use function::NixFunction;
pub use int::NixInt; pub use int::NixInt;
pub use list::NixList;
pub use null::NixNull;
pub use path::NixPath;
pub use string::NixString; pub use string::NixString;
pub use thunk::NixThunk;
use std::cell::RefCell;
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc;
use crate::EvalState;
use crate::errors::ErrorContext;
use crate::sys; 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::wrappers::AsInnerPtr;
use crate::util::{panic_issue_call_failed, wrap};
pub trait NixValue: Drop + Display + Debug + AsInnerPtr<sys::nix_value> { pub trait NixValue: Drop + Display + Debug + AsInnerPtr<sys::nix_value> {
/// TODO /// TODO
fn type_id(&self) -> sys::ValueType; fn id(&self) -> sys::ValueType;
/// TODO /// TODO
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self; fn new(inner: NonNull<sys::nix_value>) -> 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!(),
}
}
} }

View file

@ -1,63 +0,0 @@
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 }
}
}

View file

@ -1,88 +0,0 @@
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
}
}

View file

@ -1,19 +1,17 @@
use std::cell::RefCell; use std::cell::LazyCell;
use std::ffi::c_void;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc;
use super::NixValue; use super::NixValue;
use crate::errors::ErrorContext; use crate::errors::ErrorContext;
use crate::expr::RealisedString;
use crate::util::panic_issue_call_failed; use crate::util::panic_issue_call_failed;
use crate::util::wrap; use crate::util::wrap;
use crate::util::wrappers::AsInnerPtr; use crate::util::wrappers::AsInnerPtr;
use crate::{EvalState, sys}; use crate::{sys, NixideResult};
pub struct NixString { pub struct NixString {
inner: NonNull<sys::nix_value>, inner: NonNull<sys::nix_value>,
state: Rc<RefCell<EvalState>>,
value: String, value: String,
} }
@ -57,28 +55,23 @@ impl AsInnerPtr<sys::nix_value> for NixString {
impl NixValue for NixString { impl NixValue for NixString {
#[inline] #[inline]
fn type_id(&self) -> sys::ValueType { fn id(&self) -> sys::ValueType {
sys::ValueType_NIX_TYPE_STRING sys::ValueType_NIX_TYPE_STRING
} }
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<EvalState>>) -> Self { fn new(inner: NonNull<sys::nix_value>) -> Self {
let value = wrap::nix_string_callback!( // wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe { // sys::nix_get_int(ctx.as_ptr(), inner.as_ptr())
sys::nix_get_string( // })
ctx.as_ptr(), // .unwrap_or_else(|err| {
inner.as_ptr(), // panic_issue_call_failed!(
Some(callback), // "`sys::nix_get_int` failed for valid `NixString` ({})",
userdata as *mut c_void, // err
); // )
} // })
) // };
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
Self { Self { inner, value }
inner,
state,
value,
}
} }
} }

View file

@ -1,84 +0,0 @@
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()))
}
}

View file

@ -1,7 +1,5 @@
// #![warn(missing_docs)] // #![warn(missing_docs)]
#![cfg_attr(nightly, feature(fn_traits))]
pub extern crate libc; pub extern crate libc;
pub extern crate nixide_sys as sys; pub extern crate nixide_sys as sys;
@ -19,11 +17,11 @@ mod flake;
mod store; mod store;
pub use errors::{NixError, NixideError, NixideResult}; pub use errors::{NixError, NixideError, NixideResult};
pub use verbosity::{NixVerbosity, set_verbosity}; pub use verbosity::{set_verbosity, NixVerbosity};
pub use version::NixVersion; pub use version::NixVersion;
#[cfg(feature = "expr")] #[cfg(feature = "expr")]
pub use expr::{EvalState, EvalStateBuilder, Value}; pub use expr::{EvalState, EvalStateBuilder, Value, ValueType};
#[cfg(feature = "store")] #[cfg(feature = "store")]
pub use store::{Store, StorePath}; pub use store::{Store, StorePath};

View file

@ -1,5 +1,4 @@
mod cchar_ptr; mod cchar_ptr_ext;
mod slice;
pub(crate) use cchar_ptr::{AsCPtr, CCharPtrExt}; pub(crate) use cchar_ptr_ext::{AsCPtr, CCharPtrExt};
pub(crate) use slice::SliceExt; pub(crate) use stdext::*;

View file

@ -1,43 +0,0 @@
use std::iter;
use std::ptr::null_mut;
use crate::util::wrappers::AsInnerPtr;
pub trait SliceExt<T, S> {
#[allow(unused)]
fn as_c_array(&self) -> *mut *mut S;
#[allow(unused)]
fn into_c_array(self) -> *mut *mut S;
}
impl<T, S> SliceExt<T, S> for &[&T]
where
T: AsInnerPtr<S>,
{
fn as_c_array(&self) -> *mut *mut S {
let mut ptrs: Vec<*mut S> = self
.into_iter()
.map(|x| unsafe { x.as_ptr() })
.chain(iter::once(null_mut()))
.collect();
let ptr = ptrs.as_mut_ptr();
std::mem::forget(ptrs);
ptr
}
fn into_c_array(self) -> *mut *mut S {
let mut ptrs: Vec<*mut S> = self
.into_iter()
.map(|x| unsafe { x.as_ptr() })
.chain(iter::once(null_mut()))
.collect();
let ptr = ptrs.as_mut_ptr();
std::mem::forget(ptrs);
ptr
}
}

View file

@ -9,10 +9,10 @@ macro_rules! panic_issue {
macro_rules! panic_issue_call_failed { macro_rules! panic_issue_call_failed {
() => {{ () => {{
crate::util::panic_issue!("[nixide] call to `{}` failed", ::stdext::debug_name!()) crate::util::panic_issue!("[nixide] call to `{}` failed", $crate::stdext::debug_name!())
}}; }};
($($arg:expr),*) => {{ ($($arg:expr),*) => {{
crate::util::panic_issue!("[nixide] call to `{}` failed with \"{}\"", ::stdext::debug_name!(), format!($($arg),*)) crate::util::panic_issue!("[nixide] call to `{}` failed with \"{}\"", $crate::stdext::debug_name!(), format!($($arg),*))
}}; }};
} }

View file

@ -40,7 +40,7 @@ imports_layout = "HorizontalVertical" # Horizontal|Vertical|HorizontalVertical|M
indent_style = "Block" # Block|Visual indent_style = "Block" # Block|Visual
inline_attribute_width = 0 inline_attribute_width = 0
match_arm_blocks = true match_arm_blocks = true
match_arm_leading_pipes = "Never" # Preserve|Always|Never match_arm_leading_pipes = "Always" # Preserve|Always|Never
match_arm_indent = true match_arm_indent = true
match_block_trailing_comma = true match_block_trailing_comma = true
max_width = 100 max_width = 100