diff --git a/Cargo.lock b/Cargo.lock index eec43ca..9af7062 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,22 +72,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "ctor" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "424e0138278faeb2b401f174ad17e715c829512d74f3d1e81eb43365c2e0590e" -dependencies = [ - "ctor-proc-macro", - "dtor", -] - -[[package]] -name = "ctor-proc-macro" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" - [[package]] name = "doxygen-bindgen" version = "0.1.3" @@ -97,21 +81,6 @@ dependencies = [ "yap", ] -[[package]] -name = "dtor" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" -dependencies = [ - "dtor-proc-macro", -] - -[[package]] -name = "dtor-proc-macro" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" - [[package]] name = "either" version = "1.15.0" @@ -221,7 +190,6 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "nixide" version = "0.1.0" dependencies = [ - "ctor", "libc", "nixide-sys", "serial_test", diff --git a/nixide-sys/Cargo.toml b/nixide-sys/Cargo.toml index 2cc0980..0be064c 100644 --- a/nixide-sys/Cargo.toml +++ b/nixide-sys/Cargo.toml @@ -19,16 +19,14 @@ targets = [ "x86_64-unknown-linux-gnu" ] [lib] path = "lib.rs" -# NOTE: `[features]` have a 1-1 correspondence to the -# NOTE: shared libraries produced by the Nix C API. [features] -default = ["nix-util-c"] -nix-util-c = [] -nix-store-c = [] -nix-expr-c = [] -nix-fetchers-c = [] -nix-flake-c = [] -nix-main-c = [] +default = ["util"] +expr = [] +fetchers = [] +flakes = [] +store = [] +util = [] +gc = [] [build-dependencies] bindgen = { default-features = false, features = [ "logging", "runtime" ], version = "0.72.1" } diff --git a/nixide-sys/build.rs b/nixide-sys/build.rs index 0641cf8..6631264 100644 --- a/nixide-sys/build.rs +++ b/nixide-sys/build.rs @@ -20,26 +20,17 @@ impl ParseCallbacks for DoxygenCallbacks { fn main() { // Invalidate the built crate whenever the wrapper changes - 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-expr.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-main.h"); + println!("cargo:rerun-if-changed=include/wrapper.h"); + // Use pkg-config to find nix-store include and link paths + // This NEEDS to be included, or otherwise `nix_api_store.h` cannot + // be found. let libs = [ - #[cfg(feature = "nix-util-c")] - "nix-util-c", - #[cfg(feature = "nix-store-c")] - "nix-store-c", - #[cfg(feature = "nix-expr-c")] - "nix-expr-c", - #[cfg(feature = "nix-fetchers-c")] - "nix-fetchers-c", - #[cfg(feature = "nix-flake-c")] - "nix-flake-c", - #[cfg(feature = "nix-main-c")] "nix-main-c", + "nix-expr-c", + "nix-store-c", + "nix-util-c", + "nix-flake-c", ]; let lib_args: Vec = libs @@ -59,43 +50,17 @@ fn main() { .flatten() .collect(); - let mut builder = bindgen::Builder::default() + let bindings = bindgen::Builder::default() .clang_args(lib_args) + // The input header we would like to generate bindings for + .header("include/wrapper.h") // Invalidate the built crate when an included header file changes .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) // Add `doxygen_bindgen` callbacks .parse_callbacks(Box::new(DoxygenCallbacks)) // Format generated bindings with rustfmt .formatter(bindgen::Formatter::Rustfmt) - .rustfmt_configuration_file(std::fs::canonicalize(".rustfmt.toml").ok()); - - // The input headers we would like to generate bindings for - #[cfg(feature = "nix-util-c")] - { - builder = builder.header("include/nix-util.h") - } - #[cfg(feature = "nix-store-c")] - { - builder = builder.header("include/nix-store.h") - } - #[cfg(feature = "nix-expr-c")] - { - builder = builder.header("include/nix-expr.h") - } - #[cfg(feature = "nix-fetchers-c")] - { - builder = builder.header("include/nix-fetchers.h") - } - #[cfg(feature = "nix-flake-c")] - { - builder = builder.header("include/nix-flake.h") - } - #[cfg(feature = "nix-main-c")] - { - builder = builder.header("include/nix-main.h") - } - - let bindings = builder + .rustfmt_configuration_file(std::fs::canonicalize(".rustfmt.toml").ok()) // Finish the builder and generate the bindings .generate() // Unwrap the Result and panic on failure diff --git a/nixide-sys/include/nix-expr.h b/nixide-sys/include/nix-expr.h deleted file mode 100644 index b20d63b..0000000 --- a/nixide-sys/include/nix-expr.h +++ /dev/null @@ -1,10 +0,0 @@ -// Nix C API for the Nix expressions evaluator. -#include - -// Nix C API for value manipulation. -// -#include - -// Nix C API for external values. -// -#include diff --git a/nixide-sys/include/nix-fetchers.h b/nixide-sys/include/nix-fetchers.h deleted file mode 100644 index 4e80a28..0000000 --- a/nixide-sys/include/nix-fetchers.h +++ /dev/null @@ -1,3 +0,0 @@ -// Nix C API for fetcher operations. -// -#include diff --git a/nixide-sys/include/nix-flake.h b/nixide-sys/include/nix-flake.h deleted file mode 100644 index e07cfab..0000000 --- a/nixide-sys/include/nix-flake.h +++ /dev/null @@ -1,3 +0,0 @@ -// Nix C API for flake support. -// -#include diff --git a/nixide-sys/include/nix-main.h b/nixide-sys/include/nix-main.h deleted file mode 100644 index 7815125..0000000 --- a/nixide-sys/include/nix-main.h +++ /dev/null @@ -1,3 +0,0 @@ -// Nix C API for CLI support. -// -#include diff --git a/nixide-sys/include/nix-store.h b/nixide-sys/include/nix-store.h deleted file mode 100644 index 239bde5..0000000 --- a/nixide-sys/include/nix-store.h +++ /dev/null @@ -1,3 +0,0 @@ -// Nix C API for store operations. -// -#include diff --git a/nixide-sys/include/nix-util.h b/nixide-sys/include/nix-util.h deleted file mode 100644 index 8d60eed..0000000 --- a/nixide-sys/include/nix-util.h +++ /dev/null @@ -1,7 +0,0 @@ -// Nix C API for utilities. -// -// Most notably containing functions for handling -// the `nix_c_context` structure, which is used throughout -// the Nix C APIs for error handling. -// -#include diff --git a/nixide-sys/include/wrapper.h b/nixide-sys/include/wrapper.h new file mode 100644 index 0000000..30dd94e --- /dev/null +++ b/nixide-sys/include/wrapper.h @@ -0,0 +1,23 @@ +// Pure C API for store operations +#include + +// Pure C API for error handling +#include + +// Pure C API for the Nix evaluator +#include + +// Pure C API for external values +#include + +// Pure C API for value manipulation +#include + +// Pure C API for fetcher operations +#include + +// Pure C API for flake support +#include + +// Pure C API for main/CLI support +#include diff --git a/nixide/Cargo.toml b/nixide/Cargo.toml index eab4e9b..7a1b4e4 100644 --- a/nixide/Cargo.toml +++ b/nixide/Cargo.toml @@ -15,16 +15,18 @@ edition = "2024" path = "src/lib.rs" [features] -default = [] -store = ["nixide-sys/nix-store-c"] -expr = ["store", "nixide-sys/nix-expr-c"] -flake = ["store", "nixide-sys/nix-flake-c", "nixide-sys/nix-fetchers-c"] +default = ["util"] +expr = [] +fetchers = [] +flakes = [] +store = [] +util = [] +gc = [] [dependencies] libc = "0.2.183" stdext = "0.3.3" -ctor = "0.6.3" -nixide-sys = { path = "../nixide-sys", version = "0.1.0", features = ["nix-util-c", "nix-main-c"]} +nixide-sys = { path = "../nixide-sys", version = "0.1.0" } [dev-dependencies] serial_test = "3.4.0" diff --git a/nixide/src/errors/context.rs b/nixide/src/errors/context.rs index 39b1ea6..0f53046 100644 --- a/nixide/src/errors/context.rs +++ b/nixide/src/errors/context.rs @@ -180,36 +180,11 @@ impl ErrorContext { /// `nix_clear_err` only modifies the `last_err_code`, it does not /// clear all attributes of a `nix_c_context` struct. Hence all uses /// of `nix_c_context` must be careful to check the `last_err_code` regularly. - /// pub fn clear(&mut self) { unsafe { sys::nix_clear_err(self.as_ptr()); } } - /// This function never fails. - /// Nixide will always guarantee `context != nullptr`. - /// - /// # Nix C++ API Internals - /// - /// ```cpp - /// nix_err nix_set_err_msg(nix_c_context * context, nix_err err, const char * msg) - /// { - /// if (context == nullptr) { - /// // todo last_err_code - /// throw nix::Error("Nix C api error: %s", msg); - /// } - /// context->last_err_code = err; - /// context->last_err = msg; - /// return err; - /// } - /// ``` - /// - pub fn set_err(&self, err: NixError, msg: &str) { - let ptr = unsafe { self.as_ptr() }; - assert!(!ptr.is_null(), ""); - - sys::nix_set_err_msg(ptr, err.into()) - } /// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise. /// diff --git a/nixide/src/lib.rs b/nixide/src/lib.rs index dd127c6..c8f3b58 100644 --- a/nixide/src/lib.rs +++ b/nixide/src/lib.rs @@ -1,93 +1,31 @@ // #![warn(missing_docs)] +// #[allow(unused_extern_crates)] pub extern crate libc; pub extern crate nixide_sys as sys; pub(crate) mod errors; +mod expr; +// mod flake; mod stdext; +mod store; pub(crate) mod util; mod verbosity; mod version; -#[cfg(feature = "expr")] -mod expr; -#[cfg(feature = "store")] -mod store; - -#[cfg(feature = "flake")] -mod flake; - pub use errors::{NixError, NixideError, NixideResult}; +pub use expr::{EvalState, EvalStateBuilder, Value, ValueType}; +pub use store::{Store, StorePath}; pub use verbosity::NixVerbosity; pub use version::NixVersion; -#[cfg(feature = "expr")] -pub use expr::{EvalState, EvalStateBuilder, Value, ValueType}; -#[cfg(feature = "store")] -pub use store::{Store, StorePath}; - -use ctor::ctor; -use util::wrappers::AsInnerPtr as _; - -pub(crate) static mut INIT_LIBUTIL_STATUS: Option> = None; -#[cfg(feature = "store")] -pub(crate) static mut INIT_LIBSTORE_STATUS: Option> = None; -#[cfg(feature = "expr")] -pub(crate) static mut INIT_LIBEXPR_STATUS: Option> = None; - -/// # Warning +/// Sets the verbosity level /// -/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) -/// > explicitly subverts that. The code that runs in `ctor` functions -/// > should be careful to limit itself to libc functions and code -/// > 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] -fn init_libutil() { - unsafe { - INIT_LIBUTIL_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe { - sys::nix_libutil_init(ctx.as_ptr()); - })); - } -} - -/// # TODO -/// **Only run this if the "store" feature flag was enabled** -/// -/// # Warning -/// -/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) -/// > explicitly subverts that. The code that runs in `ctor` functions -/// > should be careful to limit itself to libc functions and code -/// > 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 = "store")] -fn init_libstore() { - // XXX: TODO: how do I support `sys::nix_libstore_init_no_load_config(context)`? - unsafe { - INIT_LIBSTORE_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe { - sys::nix_libutil_init(ctx.as_ptr()); - })); - } -} - -/// # TODO -/// **Only run this if the "expr" feature flag was enabled** -// -/// # Warning -/// -/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) -/// > explicitly subverts that. The code that runs in `ctor` functions -/// > should be careful to limit itself to libc functions and code -/// > 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 = "expr")] -fn init_libexpr() { - unsafe { - INIT_LIBEXPR_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe { - sys::nix_libexpr_init(ctx.as_ptr()); - })); - } +/// # Arguments +/// +/// * `context` - additional error context, used as an output +/// * `level` - verbosity level +pub fn set_verbosity() { + // nix_err nix_set_verbosity(nix_c_context * context, nix_verbosity level); + // XXX: TODO: (implement Context first) } diff --git a/nixide/src/nix_settings.rs b/nixide/src/nix_settings.rs deleted file mode 100644 index e69de29..0000000 diff --git a/nixide/src/stdext/cchar_ptr_ext.rs b/nixide/src/stdext/cchar_ptr_ext.rs index 733ed98..5d506a9 100644 --- a/nixide/src/stdext/cchar_ptr_ext.rs +++ b/nixide/src/stdext/cchar_ptr_ext.rs @@ -5,31 +5,6 @@ use std::str::from_utf8; use crate::errors::new_nixide_error; use crate::NixideResult; -pub trait AsCPtr { - fn as_c_ptr(&self) -> NixideResult<*const T>; - - fn into_c_ptr(self) -> NixideResult<*mut T>; -} - -impl AsCPtr for T -where - T: AsRef, -{ - fn as_c_ptr(&self) -> NixideResult<*const c_char> { - match CStr::from_bytes_until_nul(self.as_ref().as_bytes()) { - Ok(s) => Ok(s.as_ptr()), - Err(_) => Err(new_nixide_error!(StringNulByte)), - } - } - - fn into_c_ptr(self) -> NixideResult<*mut c_char> { - match CStr::from_bytes_until_nul(self.as_ref().as_bytes()) { - Ok(s) => Ok(s.as_ptr().cast_mut()), - Err(_) => Err(new_nixide_error!(StringNulByte)), - } - } -} - pub trait CCharPtrExt { fn to_utf8_string(self) -> NixideResult; diff --git a/nixide/src/verbosity.rs b/nixide/src/verbosity.rs index a740027..fb1918b 100644 --- a/nixide/src/verbosity.rs +++ b/nixide/src/verbosity.rs @@ -1,7 +1,4 @@ -use crate::errors::ErrorContext; use crate::sys; -use crate::util::wrappers::AsInnerPtr as _; -use crate::util::{panic_issue, panic_issue_call_failed, wrap}; /// Verbosity level /// @@ -31,46 +28,7 @@ impl From for NixVerbosity { sys::nix_verbosity_NIX_LVL_CHATTY => NixVerbosity::Chatty, sys::nix_verbosity_NIX_LVL_DEBUG => NixVerbosity::Debug, sys::nix_verbosity_NIX_LVL_VOMIT => NixVerbosity::Vomit, - value => panic_issue!( - "nixide encountered unknown `nix_verbosity` value ({})", - value - ), + _ => panic!("nixide encountered unknown `nix_verbosity` value, please submit this as an issue at https://github.com/cry128/nixide"), } } } - -impl Into for NixVerbosity { - fn into(self) -> sys::nix_verbosity { - self as sys::nix_verbosity - } -} - -/// Sets the verbosity level. -/// -/// **This function should never fail!** -/// A panic would indicate a bug in nixide itself. -/// -/// # Nix C++ API Internals -/// -/// ```cpp -/// nix_err nix_set_verbosity(nix_c_context * context, nix_verbosity level) -/// { -/// if (context) -/// context->last_err_code = NIX_OK; -/// if (level > NIX_LVL_VOMIT || level < NIX_LVL_ERROR) -/// return nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Invalid verbosity level"); -/// try { -/// nix::verbosity = static_cast(level); -/// } catch (...) { -/// return nix_context_error(context); -/// } -/// return NIX_OK; -/// } -/// ``` -/// -pub fn set_verbosity(level: NixVerbosity) { - wrap::nix_fn!(|ctx: &ErrorContext| unsafe { - sys::nix_set_verbosity(ctx.as_ptr(), level.into()); - }) - .unwrap_or_else(|err| panic_issue_call_failed!("{}", err)) -}