Expand description
#[derive(Yo)], which writes a type’s shape, its document encoding and the
indexes it declares (15 sections 3 and 4).
#[derive(Yo)]
struct Order {
#[yo(id)]
id: u64,
#[yo(index)]
status: String,
#[yo(ordered)]
total: f64,
#[yo(array)]
tags: Vec<String>,
#[yo(text)]
note: String,
}That gives Order three things. A shape, which is the canonical
description the collection is created with and every later open is checked
against. A document encoding, so a value goes into the store as YOJB without
passing through JSON text. And a list of indexes, which the collection
declares the first time it is opened, plus a Path constant per indexed
field so a query is written Order::STATUS rather than "$.status".
§The words
#[yo(id)] names the field that is the document’s id, and a type needs one
to be a document at all. #[yo(index)] asks equality, #[yo(ordered)] asks
equality and ranges, #[yo(array)] files the document under every element
of a list, and #[yo(text)] files it under every word of a string. They are
the four kinds a path index comes in and nothing is invented here.
§Why there are no dependencies
A derive is the one place a library gets to put three crates in everybody’s
build graph without being asked, and the usual three are most of what a
cold build of a small program costs. What this reads is a struct with named
fields, and a field is an attribute, a visibility, a name, a colon and some
tokens. The compiler hands that over already split into tokens, so the
parser in parse is a few hundred lines and the types themselves are
carried straight back out without ever being understood.
The cost of that choice is that the errors here are sentences rather than spans, so a mistake points at the struct rather than at the word. That is the trade, and it is written down rather than discovered.
Derive Macros§
- Yo
- Write a type’s shape, its document encoding and its indexes.