Skip to main content

Crate obj_derive

Crate obj_derive 

Source
Expand description

obj-derive — procedural macros for obj.

§⚠️ UNSTABLE — consume via obj-db, not directly

obj-derive is an implementation detail of obj-db (re-exported as obj::Document). It is published only so obj-db can depend on it and carries no SemVer guarantee as a standalone crate — depend on obj-db and write #[derive(obj::Document)]. Only obj-db’s public surface is frozen at 1.0; obj-derive is excluded from the public-api freeze gate (see docs/public-api.md).

This crate provides #[derive(obj::Document)], which emits the obj_core::Document implementation for a user struct. The derive is intentionally small — it fills in the trait’s associated constants (COLLECTION, VERSION) from optional #[obj(...)] attributes and emits an indexes() override whenever any field carries an #[obj(index ...)] attribute.

§Supported attributes

Struct-level (#[obj(...)] directly above the struct keyword):

  • version = N (integer ≥ 0) — sets Document::VERSION.
  • collection = "name" (non-empty string literal) — sets Document::COLLECTION.

Multiple #[obj(...)] attributes compose; the same scalar key (version, collection) declared twice is a compile error.

Struct-level composite (one or more occurrences compose, each adding one Composite IndexSpec):

  • index_composite(fields = ("a", "b"), name = "by_a_b") — emit a Composite IndexSpec spanning the listed fields. name defaults to the field names joined with __. The referenced fields must exist on the struct; fewer than two is a compile error.
  • index = ("a", "b") — short form, equivalent to index_composite(fields = ("a", "b")). Same downstream validation (≥ 2 fields, each declared on the struct). The default index name is the fields joined with __; there is no name = "..." slot on the short form — use index_composite when a custom name is required. Both syntaxes coexist; the short form mirrors design.md § Indexes verbatim.

Field-level (#[obj(...)] on a struct field):

  • index — emit a Standard IndexSpec for this field.
  • index = unique — emit a Unique IndexSpec for this field.
  • index = each — emit an Each IndexSpec for this field. The field type must syntactically be Vec<...> — otherwise the derive errors at compile time.
  • name = "..." — alongside any index = ..., overrides the default index name (which is the field name).

Struct-level historical schema registry (M10 #82):

  • history(v1 = OldType1, v2 = OldType2) — emit a Document::historical_schemas() override that lifts each version into a (version, DynamicSchema) pair via <OldType as ::obj::Schema>::schema(). The keys (v1, v2, …) must be vN for integer N ≥ 1; the values are arbitrary type paths. Each named type must implement ::obj::Schema (hand-impls are accepted; the derive auto-implements Schema for types that opt in via #[obj(history(...))] or #[obj(schema)]). Entries are emitted in ascending version order.
  • schema — explicitly opt the current type into a derived Schema impl WITHOUT declaring any history. Useful when the type is referenced from a future version’s history(...).

When either history(...) or schema is declared, the derive emits a companion impl ::obj::Schema block whose schema() body maps each field to a DynamicSchema variant. Scalar primitives (bool, u*, i*, f*, String) map directly; Vec<T> maps to DynamicSchema::seq(<T as Schema>::schema()); anything else delegates via <T as ::obj::Schema>::schema(), which fails to compile if T lacks a Schema impl.

§Serde requirements

The derive does NOT emit serde::Serialize or serde::Deserialize for you. Users still write #[derive(serde::Serialize, serde::Deserialize)] on the struct alongside #[derive(obj::Document)].

§Power-of-ten posture

  • Rule 4 — every function in this crate is ≤ 60 lines.
  • Rule 7 — every fallible path returns syn::Result<...>; unwrap/expect appear only on infallible primitives.
  • Rule 9 — generated code is minimal and inspectable. Every emitted item is prefixed by a // auto-generated by #[derive(Document)] marker so cargo expand output is easy to spot.

Derive Macros§

Document
Derive macro for obj::Document.