Skip to content

Commit 87b82ab

Browse files
authored
Merge pull request #29 from nixops4/readme
Update readme
2 parents edf4d62 + a02c057 commit 87b82ab

File tree

3 files changed

+204
-34
lines changed

3 files changed

+204
-34
lines changed

README.md

Lines changed: 186 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,149 @@
1+
# Nix Bindings for Rust
12

2-
# `nix_bindings_*` crates
3+
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.
34

4-
Use the Nix [C API] from Rust.
5+
## Overview
56

6-
## Build with `nix-cargo-integration`
7+
This workspace provides multiple crates that wrap different layers of the Nix C API:
78

8-
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)).
9+
- **`nix-bindings-util`** - Utility types and helpers (settings, context, version detection, string handling)
10+
- **`nix-bindings-store`** - Store operations (paths, derivations, store management)
11+
- **`nix-bindings-expr`** - Expression evaluation and type extraction
12+
- **`nix-bindings-flake`** - Flake operations
13+
- **`nix-bindings-fetchers`** - Fetcher functionality (requires Nix ≥ 2.29)
914

10-
The dependency on Nix is taken care of with the [`nix-bindings-rust` flake-parts module]().
15+
The `nix-bindings-bindgen-raw` crate contains the generated FFI bindings and is not intended for direct use.
1116

12-
Example usage:
17+
## Features
18+
19+
- **Nix evaluation** - Evaluate Nix expressions and create and extract values
20+
- **Store integration** - Interact with the Nix store, manage paths, build derivations
21+
- **Threading** - GC registration and memory management via `Drop`
22+
- **Lazy evaluation** - Fine-grained control over evaluation strictness
23+
- **Version compatibility** - Conditional compilation for different Nix versions
24+
25+
## Quick Start
26+
27+
Add the crates you need to your `Cargo.toml`:
28+
29+
```toml
30+
[dependencies]
31+
nix-bindings-store = { git = "https://github.com/nixops4/nix-bindings-rust" }
32+
nix-bindings-expr = { git = "https://github.com/nixops4/nix-bindings-rust" }
33+
```
34+
35+
Basic example:
36+
37+
```rust
38+
use nix_bindings_expr::eval_state::{EvalState, init, gc_register_my_thread};
39+
use nix_bindings_store::store::Store;
40+
use std::collections::HashMap;
41+
42+
fn main() -> anyhow::Result<()> {
43+
// Initialize Nix library and register thread with GC
44+
init()?;
45+
let guard = gc_register_my_thread()?;
46+
47+
// Open a store connection and create an evaluation state
48+
let store = Store::open(None, HashMap::new())?;
49+
let mut eval_state = EvalState::new(store, [])?;
50+
51+
// Evaluate a Nix expression
52+
let value = eval_state.eval_from_string("[1 2 3]", "<example>")?;
53+
54+
// Extract typed values
55+
let elements: Vec<_> = eval_state.require_list_strict(&value)?;
56+
for element in elements {
57+
let num = eval_state.require_int(&element)?;
58+
println!("Element: {}", num);
59+
}
60+
61+
drop(guard);
62+
Ok(())
63+
}
64+
```
65+
66+
## Usage Examples
67+
68+
### Evaluating Nix Expressions
69+
70+
```rust
71+
use nix_bindings_expr::eval_state::EvalState;
72+
73+
// Evaluate and extract different types
74+
let int_value = eval_state.eval_from_string("42", "<example>")?;
75+
let num = eval_state.require_int(&int_value)?;
76+
77+
let str_value = eval_state.eval_from_string("\"hello\"", "<example>")?;
78+
let text = eval_state.require_string(&str_value)?;
79+
80+
let attr_value = eval_state.eval_from_string("{ x = 1; y = 2; }", "<example>")?;
81+
let attrs = eval_state.require_attrs(&attr_value)?;
82+
```
83+
84+
### Working with Lists
85+
86+
```rust
87+
let list_value = eval_state.eval_from_string("[1 2 3 4 5]", "<example>")?;
88+
89+
// Lazy: check size without evaluating elements
90+
let size = eval_state.require_list_size(&list_value)?;
91+
92+
// Selective: evaluate only accessed elements
93+
if let Some(first) = eval_state.require_list_select_idx_strict(&list_value, 0)? {
94+
let value = eval_state.require_int(&first)?;
95+
}
96+
97+
// Strict: evaluate all elements
98+
let all_elements: Vec<_> = eval_state.require_list_strict(&list_value)?;
99+
```
100+
101+
### Thread Safety
102+
103+
Before using `EvalState` in a thread, register with the garbage collector:
104+
105+
```rust
106+
use nix_bindings_expr::eval_state::{init, gc_register_my_thread};
107+
108+
init()?; // Once per process
109+
let guard = gc_register_my_thread()?; // Once per thread
110+
// ... use EvalState ...
111+
drop(guard); // Unregister when done
112+
```
113+
114+
For more examples, see the documentation in each crate's source code.
115+
116+
## Nix Version Compatibility
117+
118+
The crates use conditional compilation to support multiple Nix versions:
119+
120+
- **`nix-bindings-fetchers`** requires Nix ≥ 2.29
121+
- Some features in other crates require specific Nix versions
122+
123+
The build system automatically detects the Nix version and enables appropriate features.
124+
125+
## Integration with Nix Projects
126+
127+
These crates use [nix-cargo-integration] for seamless integration with Nix builds. To use them in your Nix project:
13128

14129
```nix
15130
{
16-
outputs =
17-
inputs@{ self, flake-parts, ... }:
18-
flake-parts.lib.mkFlake { inherit inputs; }
19-
{
131+
inputs = {
132+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
133+
flake-parts.url = "github:hercules-ci/flake-parts";
134+
nix-cargo-integration.url = "github:90-008/nix-cargo-integration";
135+
nix-bindings-rust.url = "github:nixops4/nix-bindings-rust";
136+
};
137+
138+
outputs = inputs@{ flake-parts, ... }:
139+
flake-parts.lib.mkFlake { inherit inputs; } {
20140
imports = [
21141
inputs.nix-cargo-integration.flakeModule
22142
inputs.nix-bindings-rust.modules.flake.default
23143
];
24144
25145
perSystem = { config, pkgs, ... }: {
26-
# optional:
146+
# Optional: override Nix package
27147
nix-bindings-rust.nixPackage = pkgs.nix;
28148
29149
nci.projects."myproject" = {
@@ -36,18 +156,68 @@ Example usage:
36156
}
37157
```
38158

39-
## Hacking
159+
See the [nix-cargo-integration documentation][nix-cargo-integration] for more options.
40160

41-
The following will open a shell with dependencies, and install pre-commit for automatic formatting.
161+
## Development
162+
163+
### Getting Started
42164

43165
```console
44166
$ nix develop
45167
```
46168

47-
### VSCode
169+
### Building
170+
171+
```bash
172+
# Build specific crates (release mode)
173+
nix build .#nix-bindings-store-release
174+
nix build .#nix-bindings-expr-release
175+
176+
# Build with Cargo (in dev shell)
177+
cargo build
178+
cargo build --release
179+
```
180+
181+
### Testing
182+
183+
```bash
184+
# Run tests for specific crates via Nix (recommended - includes proper store setup)
185+
nix build .#checks.x86_64-linux.nix-bindings-store-tests
186+
nix build .#checks.x86_64-linux.nix-bindings-expr-tests
187+
188+
# Run all checks (tests + clippy + formatting)
189+
nix flake check
190+
191+
# Run tests with Cargo (in dev shell)
192+
cargo test
193+
194+
# Run specific test
195+
cargo test test_name
196+
```
197+
198+
### Memory Testing
199+
200+
For FFI memory leak testing with valgrind, see [doc/hacking/test-ffi.md](doc/hacking/test-ffi.md).
201+
202+
### Code Formatting
203+
204+
```bash
205+
treefmt
206+
```
207+
208+
### IDE Setup
209+
210+
For VSCode, load the dev shell via Nix Env Selector extension or direnv.
211+
212+
## Documentation
213+
214+
- [Nix C API Reference][C API]
215+
- [nix-cargo-integration][nix-cargo-integration]
216+
- [Hacking Guide](doc/hacking/test-ffi.md)
48217

49-
#### rust-analyzer
218+
## License
50219

51-
If the rust-analyzer extension fails, make sure the devShell was loaded into VSCode via Nix Env Selector or direnv.
220+
See [LICENSE](LICENSE) file in the repository.
52221

53222
[C API]: https://nix.dev/manual/nix/latest/c-api.html
223+
[nix-cargo-integration]: https://github.com/90-008/nix-cargo-integration#readme

flake.lock

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
flake-parts.url = "github:hercules-ci/flake-parts";
66
nix.url = "github:NixOS/nix";
77
nix.inputs.nixpkgs.follows = "nixpkgs";
8-
nix-cargo-integration.url = "github:yusdacra/nix-cargo-integration";
8+
nix-cargo-integration.url = "github:90-008/nix-cargo-integration";
99
nix-cargo-integration.inputs.nixpkgs.follows = "nixpkgs";
1010
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
1111
};

0 commit comments

Comments
 (0)