# GraphDDB Rust Runtime
A Rust (edition 2021) runtime that interprets the language-neutral GraphDDB IR
(`manifest.json` + `operations.json`, `SPEC_VERSION` 1.1) and executes the
validated access patterns against DynamoDB via
[`aws-sdk-dynamodb`](https://crates.io/crates/aws-sdk-dynamodb). It is a faithful
port of the Python reference runtime (`python/graphddb_runtime`) and is proven, by
the conformance harness (`conformance/`), to produce results **identical** to the
TypeScript live executor and the Python / PHP runtimes for every golden case.
TypeScript remains the single source of truth: this runtime never re-implements
the GraphDDB DSL — it is a pure interpreter of the IR the TS generator emits, so
`src/` is never touched (issue #214, epic #211).
## Layout
- `graphddb_runtime/` — the library crate (the runtime).
- `conformance_runner/` — the `rust_runner` binary the conformance harness drives
(the structural counterpart of `conformance/py_runner.py` / `php_runner.php`).
## Usage
```rust
use std::sync::Arc;
use aws_sdk_dynamodb::Client;
use graphddb_runtime::{AwsDynamoClient, GraphDDBRuntime, RuntimeLimits};
use serde_json::json;
# async fn demo() -> Result<(), Box<dyn std::error::Error>> {
let conf = aws_config::load_from_env().await;
let client = Arc::new(AwsDynamoClient::new(Client::new(&conf)));
let runtime = GraphDDBRuntime::from_paths(
client,
"manifest.json",
"operations.json",
None, // optional logical→physical table mapping
Some(RuntimeLimits::default()),
)?;
// Params are keyed by the original definition names; results are serde_json::Value.
let user = runtime
.execute_query("getUser", json!({"userId": "alice"}).as_object().unwrap())
.await?;
runtime
.execute_command("addGroupMember", json!({"groupId": "eng", "userId": "u1", "role": "member"}).as_object().unwrap())
.await?;
# Ok(()) }
```
The consumer API mirrors the Python surface: `execute_query`, `execute_command`,
`execute_transaction`, `execute_query_method`, `execute_command_method`, and
`explain` (all async). Typed bindings (the Python `types.py` / `repositories.py`
layer) are out of scope for this crate — the runtime works directly on the IR.
## Development
```bash
cargo build
cargo test # unit tests + the python3 number-parity fuzz (skips if no python3)
cargo clippy --all-targets -- -D warnings
cargo fmt --all --check
```
## Number / cursor parity
Pagination cursors and DynamoDB number encoding are **byte-identical** to the
Python reference (the parity SSoT):
- a cursor `N` token is an exact full-precision integer when the value is integral,
else `float(Decimal(x))` rendered by CPython's `json.dumps(float)` formatter
(deliberately lossy — see `ddb_number.rs`);
- float → string reproduces CPython's `repr(float)` exactly, including its
fixed-vs-scientific threshold, signed zero-padded exponents, and the
round-half-to-even shortest-digit tie-break (`pyfloat.rs`).
Every numeric test vector is regenerated from `python3` at test time (a fuzz over
thousands of doubles / decimal strings) — never pinned to Rust's own output.
## Conformance
The Rust dimension is wired into `conformance/run.ts` (tag `rust:`). Bring up
DynamoDB Local (`npm run docker:up`) and run:
```bash
npx tsx conformance/run.ts
```
The Rust results are deep-compared against the TS live executor for every case,
alongside the Python and PHP dimensions. CI (`.github/workflows/rust.yml`) runs
build/test/clippy/fmt, the conformance harness, a `rust-*` mutation non-vacuity
probe, and the `git diff -- src/` guard.