This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the Rust SDK for Hegel, a universal property-based testing framework. The SDK communicates with a Python server (powered by Hypothesis) via Unix sockets to generate test data.
just test # cargo test
just format # cargo fmt
just docs # cargo doc --open --all-features
cargo test test_name # Run single test
cargo test --all-features # Run tests including optional featureshegel-rust/
├── src/
│ ├── lib.rs # Public API: hegel(), Hegel builder, assume(), note()
│ ├── cbor_helpers.rs # Macros and helpers for ciborium::Value (cbor_map!, cbor_array!, map_get, etc.)
│ ├── runner.rs # Spawns hegel CLI, manages socket server
│ └── gen/ # Generator implementations
│ ├── mod.rs # Generate trait, socket communication, thread-local state
│ ├── primitives.rs # unit(), booleans(), just(), just_any()
│ ├── numeric.rs # integers(), floats() with bounds
│ ├── strings.rs # text(), from_regex()
│ ├── formats.rs # emails(), urls(), dates(), ip_addresses(), etc.
│ ├── collections.rs # vecs(), hashsets(), hashmaps()
│ ├── tuples.rs # tuples(), tuples3()
│ ├── combinators.rs # one_of!(), optional(), sampled_from(), BoxedGenerator
│ ├── fixed_dict.rs # fixed_dicts() for JSON objects
│ ├── default.rs # DefaultGenerator trait implementations
│ ├── macros.rs # one_of!(), derive_generator!() macros
│ ├── binary.rs # binary() for Vec<u8> generation
│ ├── random.rs # randoms() for RNG generation (requires "rand" feature)
│ └── value.rs # HegelValue wrapper for NaN/Infinity handling
├── hegel-derive/ # Proc macro crate for #[derive(Generate)]
│ └── src/lib.rs # Derives generators for structs and enums
└── build.rs # Auto-installs hegel CLI via uv if not on PATH
rand: Enablesgen::randoms()for generatingrand::RngCoreimplementations
HEGEL_DEBUG=1: Log all socket requests/responses to stderr
The SDK creates a socket path and spawns the hegel CLI as a subprocess. Hegeld binds to the socket and listens for connections. The SDK then connects as a client, and a single persistent connection is maintained for the program run. Multiple tests can be executed over this connection. The build script (build.rs) automatically installs Python and hegel into cargo's OUT_DIR/hegel via uv if not found on PATH.
The protocol uses CBOR encoding over multiplexed channels. For each test:
- SDK sends
run_testrequest on control channel - Hegeld sends
test_caseevents with channel IDs for each test case - SDK runs test function, sending
generate/start_span/stop_spanrequests on the test channel - SDK sends
mark_completewith status (VALID, INVALID, or INTERESTING) - After all test cases, hegeld sends
test_donewith results`
The SDK uses thread-local storage for:
IS_LAST_RUN: Whether this is the final replay for counterexample outputCONNECTION: The active socket connection with span depth tracking
Generators implement the Generate<T> trait:
schema(): Returns a CBOR schema (asciborium::Value) describing generated values (enables single-request composition)generate(): Produces a value, either via schema or compositional fallback
When schema() returns Some, the SDK sends one request. When None (after map/filter), it falls back to multiple requests with span grouping for shrinking.
Spans (start_span/stop_span) group related generation calls, helping Hypothesis understand data structure for effective shrinking. Labels in gen::labels identify span types (LIST, TUPLE, ONE_OF, etc.).
- Create a builder struct with configuration fields
- Implement
Generate<T>withschema()andgenerate() - Export a factory function from
gen/mod.rs - If the generated type should work with
#[derive(Generate)], implementDefaultGenerator
#[derive(Generate)] creates a <Type>Generator struct with:
new(): UsesDefaultGeneratorfor all fieldswith_<field>(gen): Builder methods to customize field generators
For enums, it also creates <Enum><Variant>Generator for each data variant.