Skip to main content

Crate yo_derive

Crate yo_derive 

Source
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,
    #[yo(vector = 3)]
    embedding: Vec<f32>,
}

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.

#[yo(vector = 384)] on a Vec<f32> asks for a vector index over the embedding that field holds, which is the one mark that takes a number, because how wide a collection’s vectors are is decided when the type is written and there is no reason to find it out from the first document instead. It gives the type a Vector constant, so a nearest neighbour search names the field the same way an equality lookup does.

§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.