From 9c215f2d4bcda1941e49a9ec7015a4a154d09e3a Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 16 Dec 2025 01:48:19 +0100 Subject: [PATCH 1/2] maint: nci has changed owners --- flake.lock | 34 +++++++++++++++++----------------- flake.nix | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/flake.lock b/flake.lock index 358d842..a2e04cd 100644 --- a/flake.lock +++ b/flake.lock @@ -27,11 +27,11 @@ "pyproject-nix": "pyproject-nix" }, "locked": { - "lastModified": 1765228272, - "narHash": "sha256-duTz4J4NP1edl/ZBdwZPduPM8j6g0yzjb8YH91T9vU0=", + "lastModified": 1765450682, + "narHash": "sha256-nZjNYEvNKZRF0+koTN2azGWbGlsvLNUTF6PcC0eqTa4=", "owner": "nix-community", "repo": "dream2nix", - "rev": "83c430ce6b6aedf149c5259f066bfff808722dbd", + "rev": "343053a4dfa53ce8abfc35e918cd4ab990abc58d", "type": "github" }, "original": { @@ -196,15 +196,15 @@ "treefmt": "treefmt" }, "locked": { - "lastModified": 1765261286, - "narHash": "sha256-Ll29VFrT+VpnP4HG5LiL33IXuiz6cF2WfTwXONwMj7E=", - "owner": "yusdacra", + "lastModified": 1765606778, + "narHash": "sha256-Rngkpanmds2XYIpFav634N2EJnmCVGlT4j04rd/XCLE=", + "owner": "90-008", "repo": "nix-cargo-integration", - "rev": "92639295bbe953e4c8c32cbffa32dcb0a441118b", + "rev": "f5b7a1543357cd2071cc847a9ae378328d7caa57", "type": "github" }, "original": { - "owner": "yusdacra", + "owner": "90-008", "repo": "nix-cargo-integration", "type": "github" } @@ -280,11 +280,11 @@ ] }, "locked": { - "lastModified": 1763759067, - "narHash": "sha256-LlLt2Jo/gMNYAwOgdRQBrsRoOz7BPRkzvNaI/fzXi2Q=", + "lastModified": 1765495779, + "narHash": "sha256-MhA7wmo/7uogLxiewwRRmIax70g6q1U/YemqTGoFHlM=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2cccadc7357c0ba201788ae99c4dfa90728ef5e0", + "rev": "5635c32d666a59ec9a55cab87e898889869f7b71", "type": "github" }, "original": { @@ -326,11 +326,11 @@ ] }, "locked": { - "lastModified": 1752481895, - "narHash": "sha256-luVj97hIMpCbwhx3hWiRwjP2YvljWy8FM+4W9njDhLA=", + "lastModified": 1763017646, + "narHash": "sha256-Z+R2lveIp6Skn1VPH3taQIuMhABg1IizJd8oVdmdHsQ=", "owner": "pyproject-nix", "repo": "pyproject.nix", - "rev": "16ee295c25107a94e59a7fc7f2e5322851781162", + "rev": "47bd6f296502842643078d66128f7b5e5370790c", "type": "github" }, "original": { @@ -355,11 +355,11 @@ ] }, "locked": { - "lastModified": 1765248027, - "narHash": "sha256-ngar+yP06x3+2k2Iey29uU0DWx5ur06h3iPBQXlU+yI=", + "lastModified": 1765593578, + "narHash": "sha256-qbl874bCIy9+OLImdfBfZ9ITUDDjjTAB04Dk4PlZFV0=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "7b50ad68415ae5be7ee4cc68fa570c420741b644", + "rev": "348b94ed9ddffccdf1a65582a2dcff0a4a3eeeb4", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index e323a3c..5d386f1 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,7 @@ flake-parts.url = "github:hercules-ci/flake-parts"; nix.url = "github:NixOS/nix"; nix.inputs.nixpkgs.follows = "nixpkgs"; - nix-cargo-integration.url = "github:yusdacra/nix-cargo-integration"; + nix-cargo-integration.url = "github:90-008/nix-cargo-integration"; nix-cargo-integration.inputs.nixpkgs.follows = "nixpkgs"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; }; From a02c057666c4e854db628fe7e8eec0098c4e0ca0 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 16 Dec 2025 01:48:56 +0100 Subject: [PATCH 2/2] doc: Update README --- README.md | 202 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 186 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5e85853..5538048 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,149 @@ +# Nix Bindings for Rust -# `nix_bindings_*` crates +Rust bindings for the Nix [C API], providing safe, idiomatic Rust interfaces to Nix's core functionality including store operations, expression evaluation, and flake management. -Use the Nix [C API] from Rust. +## Overview -## Build with `nix-cargo-integration` +This workspace provides multiple crates that wrap different layers of the Nix C API: -The development environment and building with Nix are taken care of by [nix-cargo-integration](https://github.com/90-008/nix-cargo-integration#readme) ([options](https://flake.parts/options/nix-cargo-integration.html)). +- **`nix-bindings-util`** - Utility types and helpers (settings, context, version detection, string handling) +- **`nix-bindings-store`** - Store operations (paths, derivations, store management) +- **`nix-bindings-expr`** - Expression evaluation and type extraction +- **`nix-bindings-flake`** - Flake operations +- **`nix-bindings-fetchers`** - Fetcher functionality (requires Nix ≥ 2.29) -The dependency on Nix is taken care of with the [`nix-bindings-rust` flake-parts module](). +The `nix-bindings-bindgen-raw` crate contains the generated FFI bindings and is not intended for direct use. -Example usage: +## Features + +- **Nix evaluation** - Evaluate Nix expressions and create and extract values +- **Store integration** - Interact with the Nix store, manage paths, build derivations +- **Threading** - GC registration and memory management via `Drop` +- **Lazy evaluation** - Fine-grained control over evaluation strictness +- **Version compatibility** - Conditional compilation for different Nix versions + +## Quick Start + +Add the crates you need to your `Cargo.toml`: + +```toml +[dependencies] +nix-bindings-store = { git = "https://github.com/nixops4/nix-bindings-rust" } +nix-bindings-expr = { git = "https://github.com/nixops4/nix-bindings-rust" } +``` + +Basic example: + +```rust +use nix_bindings_expr::eval_state::{EvalState, init, gc_register_my_thread}; +use nix_bindings_store::store::Store; +use std::collections::HashMap; + +fn main() -> anyhow::Result<()> { + // Initialize Nix library and register thread with GC + init()?; + let guard = gc_register_my_thread()?; + + // Open a store connection and create an evaluation state + let store = Store::open(None, HashMap::new())?; + let mut eval_state = EvalState::new(store, [])?; + + // Evaluate a Nix expression + let value = eval_state.eval_from_string("[1 2 3]", "")?; + + // Extract typed values + let elements: Vec<_> = eval_state.require_list_strict(&value)?; + for element in elements { + let num = eval_state.require_int(&element)?; + println!("Element: {}", num); + } + + drop(guard); + Ok(()) +} +``` + +## Usage Examples + +### Evaluating Nix Expressions + +```rust +use nix_bindings_expr::eval_state::EvalState; + +// Evaluate and extract different types +let int_value = eval_state.eval_from_string("42", "")?; +let num = eval_state.require_int(&int_value)?; + +let str_value = eval_state.eval_from_string("\"hello\"", "")?; +let text = eval_state.require_string(&str_value)?; + +let attr_value = eval_state.eval_from_string("{ x = 1; y = 2; }", "")?; +let attrs = eval_state.require_attrs(&attr_value)?; +``` + +### Working with Lists + +```rust +let list_value = eval_state.eval_from_string("[1 2 3 4 5]", "")?; + +// Lazy: check size without evaluating elements +let size = eval_state.require_list_size(&list_value)?; + +// Selective: evaluate only accessed elements +if let Some(first) = eval_state.require_list_select_idx_strict(&list_value, 0)? { + let value = eval_state.require_int(&first)?; +} + +// Strict: evaluate all elements +let all_elements: Vec<_> = eval_state.require_list_strict(&list_value)?; +``` + +### Thread Safety + +Before using `EvalState` in a thread, register with the garbage collector: + +```rust +use nix_bindings_expr::eval_state::{init, gc_register_my_thread}; + +init()?; // Once per process +let guard = gc_register_my_thread()?; // Once per thread +// ... use EvalState ... +drop(guard); // Unregister when done +``` + +For more examples, see the documentation in each crate's source code. + +## Nix Version Compatibility + +The crates use conditional compilation to support multiple Nix versions: + +- **`nix-bindings-fetchers`** requires Nix ≥ 2.29 +- Some features in other crates require specific Nix versions + +The build system automatically detects the Nix version and enables appropriate features. + +## Integration with Nix Projects + +These crates use [nix-cargo-integration] for seamless integration with Nix builds. To use them in your Nix project: ```nix { - outputs = - inputs@{ self, flake-parts, ... }: - flake-parts.lib.mkFlake { inherit inputs; } - { + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + nix-cargo-integration.url = "github:90-008/nix-cargo-integration"; + nix-bindings-rust.url = "github:nixops4/nix-bindings-rust"; + }; + + outputs = inputs@{ flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { imports = [ inputs.nix-cargo-integration.flakeModule inputs.nix-bindings-rust.modules.flake.default ]; perSystem = { config, pkgs, ... }: { - # optional: + # Optional: override Nix package nix-bindings-rust.nixPackage = pkgs.nix; nci.projects."myproject" = { @@ -36,18 +156,68 @@ Example usage: } ``` -## Hacking +See the [nix-cargo-integration documentation][nix-cargo-integration] for more options. -The following will open a shell with dependencies, and install pre-commit for automatic formatting. +## Development + +### Getting Started ```console $ nix develop ``` -### VSCode +### Building -#### rust-analyzer +```bash +# Build specific crates (release mode) +nix build .#nix-bindings-store-release +nix build .#nix-bindings-expr-release -If the rust-analyzer extension fails, make sure the devShell was loaded into VSCode via Nix Env Selector or direnv. +# Build with Cargo (in dev shell) +cargo build +cargo build --release +``` + +### Testing + +```bash +# Run tests for specific crates via Nix (recommended - includes proper store setup) +nix build .#checks.x86_64-linux.nix-bindings-store-tests +nix build .#checks.x86_64-linux.nix-bindings-expr-tests + +# Run all checks (tests + clippy + formatting) +nix flake check + +# Run tests with Cargo (in dev shell) +cargo test + +# Run specific test +cargo test test_name +``` + +### Memory Testing + +For FFI memory leak testing with valgrind, see [doc/hacking/test-ffi.md](doc/hacking/test-ffi.md). + +### Code Formatting + +```bash +treefmt +``` + +### IDE Setup + +For VSCode, load the dev shell via Nix Env Selector extension or direnv. + +## Documentation + +- [Nix C API Reference][C API] +- [nix-cargo-integration][nix-cargo-integration] +- [Hacking Guide](doc/hacking/test-ffi.md) + +## License + +See [LICENSE](LICENSE) file in the repository. [C API]: https://nix.dev/manual/nix/latest/c-api.html +[nix-cargo-integration]: https://github.com/90-008/nix-cargo-integration#readme