obj-db 1.1.2

Embedded document database. Stable file format, full ACID, single-file portability.
Documentation
[package]
name = "obj-db"
description = "Embedded document database. Stable file format, full ACID, single-file portability."
version.workspace = true
edition.workspace = true
license.workspace = true
rust-version.workspace = true
repository.workspace = true
authors.workspace = true
homepage = "https://github.com/uname-n/obj"
documentation = "https://docs.rs/obj-db"
readme = "README.md"
keywords = ["database", "embedded", "document", "acid", "storage"]
categories = ["database", "database-implementations", "data-structures"]

# docs.rs (release-review #38): build the docs with every feature on so
# the rendered API includes the serde / tracing / compression /
# encryption / async surface — all features are off by default, so
# without this docs.rs would show only the bare baseline.
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

# Package is published to crates.io as `obj-db`
# The library name stays `obj` so downstream users write `use obj::Db`
# — they just `cargo add obj-db` to pull it in.
[lib]
name = "obj"

[dependencies]
obj-core = { path = "../obj-core", version = "1.1.2" }
# M9: `obj-derive` is re-exported as `obj::Document` (proc-macro) so
# users write `#[derive(obj::Document)]` against this single crate.
obj-derive = { path = "../obj-derive", version = "1.1.2" }
# Phase 2A (issue #6): `serde` is an opt-in feature on obj-db. When
# the `serde` feature is enabled, public obj-db types derive
# `Serialize` + `Deserialize` and the two traits are re-exported from
# the crate root. `obj-core` already depends on `serde` unconditionally
# (postcard needs it on disk), so flipping this feature on costs
# essentially nothing at the binary level — it only widens the public
# API surface. MIT OR Apache-2.0.
serde = { version = "1", features = ["derive"], optional = true }
# Phase 2B (issue #7): `tracing` is opt-in. When enabled, obj-db
# emits structured spans around `Db::open`, transaction begin /
# commit / rollback, `Query::fetch` / `count`, `integrity_check`,
# and the obj-core pager checkpoint. The dependency is optional so
# `cargo build --no-default-features` adds no new transitive deps.
# Apache-2.0 OR MIT.
tracing = { version = "0.1", optional = true }
# Phase 5 (issue #10): `blocking` is the runtime-agnostic
# blocking-task executor used by the opt-in `async` feature. It
# spawns a lazily-initialised thread pool and exposes
# `blocking::unblock(closure).await` — compatible with Tokio,
# async-std, smol, and any other async runtime. The dependency is
# optional so `cargo build --no-default-features` adds no new
# transitive deps. Apache-2.0 OR MIT.
blocking = { version = "1", optional = true }
# #87 (perf): OPTIONAL, NON-DEFAULT. `mimalloc` is only pulled in by
# the `fast-alloc` feature, which exists purely so the bench binaries
# can register a `#[global_allocator]` for an apples-to-apples
# allocator A/B. The `obj` LIBRARY never registers a global allocator
# (a library must not force a process-global allocator on downstreams
# — issue #87 guardrail); the static lives only in the bench binary.
# `mimalloc` is the workspace's first vendored-C build dep, so it is
# gated behind a feature that is off by default: the baseline build,
# public-api surface, Miri run, and `forbid-unsafe` posture are all
# unchanged unless `--features fast-alloc` is passed explicitly.
mimalloc = { version = "0.1", optional = true }

[features]
# Phase 2A (issue #6): no default features. Keeping this section
# explicit makes the intent visible to readers and to `cargo metadata`.
default = []
# Opt-in: derive `serde::Serialize` + `serde::Deserialize` on the
# public obj-db types and re-export the two traits from the crate
# root. Pure additive surface — no format-byte impact.
serde = ["dep:serde"]
# Phase 2B (issue #7): emit `tracing` spans around the obj-db
# observability surface. Propagates to obj-core so the pager's
# checkpoint span lights up under the same flag. Off by default —
# zero span overhead in the baseline build.
tracing = ["dep:tracing", "obj-core/tracing"]
# Phase 3 (issue #8): LZ4 per-page page compression. Propagates to
# obj-core. Off by default. v1.0 writers always stamp
# `format_minor = 2`; compression is signalled per-page by a flag
# bit, not by the minor version. A build WITHOUT this feature reads
# uncompressed files normally and refuses any file that contains an
# LZ4-compressed page with `Error::FormatFeatureUnsupported`.
compression = ["obj-core/compression"]
# Phase 4 (issue #9): ChaCha20-Poly1305 per-page at-rest
# encryption. Propagates to obj-core. Off by default. v1.0 writers
# always stamp `format_minor = 2`; encryption is signalled by
# `feature_flags` bit 1 in the page-0 header, not by the minor. A
# build WITHOUT this feature refuses to open an encrypted file with
# `Error::FormatFeatureUnsupported`.
encryption = ["obj-core/encryption"]
# Phase 5 (issue #10): runtime-agnostic async surface mirroring
# the blocking `Db` / `Collection` / `Query` API behind a new
# `obj::asynchronous` module. Work is routed through the
# `blocking` crate's process-wide thread pool — every async
# method spawns its body via `blocking::unblock(...).await`, so
# the surface composes with Tokio, async-std, smol, and any
# other runtime without per-runtime sub-features. Off by default
# — the baseline build has zero new transitive deps and zero
# async overhead. The blocking surface (`Db`, `Collection`,
# `Query`, `WriteTxn`, `ReadTxn`) is untouched: the async types
# are pure additions.
async = ["dep:blocking"]
# #87 (perf): opt-in `mimalloc` `#[global_allocator]`. NON-DEFAULT.
# Only the bench binaries register the allocator (behind
# `#[cfg(feature = "fast-alloc")]`); the `obj` library does NOT — a
# library forcing a process-global allocator collides with downstream
# applications. Enable with `cargo bench -p obj-db --features
# fast-alloc` to A/B the allocator against the system one. Off by
# default keeps the baseline dep tree free of the vendored-C build.
fast-alloc = ["dep:mimalloc"]

[dev-dependencies]
# `tempfile` provides RAII temp directories for the integration
# tests. MIT OR Apache-2.0.
tempfile = "3"
# `trybuild` drives compile-fail tests for the `#[derive(Document)]`
# proc-macro (M9 #79). MIT OR Apache-2.0.
trybuild = "1"
# `serde` derive macros for the integration test's Document
# implementations. MIT OR Apache-2.0. Cargo permits the same crate in
# both `[dependencies]` (optional, gating the `serde` feature) and
# `[dev-dependencies]` (always-on, so integration tests compile
# without `--features serde`).
serde = { version = "1", features = ["derive"] }
# Phase 2A (issue #6): the new `serde_feature` integration test
# round-trips public types through JSON. MIT OR Apache-2.0.
serde_json = "1"
# Phase 2B (issue #7): the new `tracing_feature` integration test
# attaches a capturing `Layer` to assert the opt-in `tracing`
# feature wires the six spans. MIT.
tracing-subscriber = "0.3"
# `criterion` for the M6 #48 concurrent-reader scaling bench.
# MIT OR Apache-2.0. Default features disabled to mirror the M4
# bench convention; single-threaded measurement is sufficient here
# because the bench manages its own thread fan-out.
criterion = { version = "0.5", default-features = false, features = ["cargo_bench_support"] }
# Deterministic PRNG for the bench's id-sampling so two runs of
# the bench against the same data set produce comparable numbers.
rand = "0.9"
rand_chacha = "0.9"
# M10 #82: schema-registry tests hand-encode v1 / v2 payloads via
# postcard to drive `Dynamic::from_postcard_bytes(...)`. The
# obj-core crate already pins the same major; no version skew.
# `default-features = false` mirrors obj-core (issues #39/#68): the
# tests only use the `to_allocvec` / `from_bytes` alloc path, so
# dropping postcard's `heapless-cas` default keeps heapless 0.7 +
# atomic-polyfill (RUSTSEC-2023-0089) out of the locked dev tree too.
postcard = { version = "1", default-features = false, features = ["alloc"] }
# `obj-core` is already a normal dependency above; the M7 #61
# `index_range` bench reaches into the order-preserving key encoder
# (`obj_core::index::encode_field`) to build half-open range bounds.
# A `dev-dependencies` entry is unnecessary because the public dep
# already exposes the path.
# Phase 5 (issue #10): drive the async wrapper from a real runtime
# inside the integration tests. Both runtimes ride the same
# `blocking` crate via the opt-in `async` feature — the tests
# exercise both to prove the runtime-agnostic invariant. MIT.
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
# The second runtime is `smol`: async-std was discontinued
# (RUSTSEC-2025-0052) and its own README points at smol as the
# replacement. smol has no test-attribute macro, so the companion
# test drives it via `smol::block_on`. MIT/Apache-2.0.
smol = "2"

[[bench]]
# M6 issue #48: N-reader scaling benchmark.  `harness = false`
# lets criterion own the test main.
name = "concurrent_reads"
harness = false

[[bench]]
# M7 issue #61: `find_unique` warm-cache latency benchmark.
name = "index_lookup"
harness = false

[[bench]]
# M7 issue #61: `index_range` vs full-scan ratio benchmark.
name = "index_range"
harness = false

[[bench]]
# M8 issue #69: `Db::all::<T>()` 100k-doc collection-scan benchmark
# (M8 exit gate, perf side). `OBJ_BENCH_ENFORCE=1` upgrades the
# informational TARGET_MS check to a hard failure.
name = "collection_scan"
harness = false

[[bench]]
# M11 issue #94: `Db::integrity_check` 1 GB benchmark (M11 exit
# gate, perf side). Asserts the integrity walk completes within an
# order of magnitude of a `wc -c` proxy derived from the on-disk
# file size. `OBJ_BENCH_ENFORCE=1` upgrades the informational
# print to a hard failure.
name = "integrity_1gb"
harness = false

[[bench]]
# M14 issue #119: design.md 8-row perf-table reproduction harness.
# Runs every row under criterion + emits a markdown table to stdout
# and `target/criterion/perf_table/perf_table.md`.
# `OBJ_BENCH_ENFORCE=1` upgrades the print to a hard gate (each row
# must stay within 10× of its design.md target).
name = "perf_table"
harness = false

[[bench]]
# Lean human-facing perf-iteration bench (issue #78). NOT a CI gate
# bench — pure criterion, short windows, ~256-doc populate. Use
# `--save-baseline` / `--baseline` to compare across changes.
name = "quick"
harness = false

[lints]
workspace = true