Kite

toml

std/toml — reading and writing TOML.

Written in Kite, on the same shape as std/json: a parse returns (Toml, error), and a malformed document is a value to handle rather than something thrown. Positions are threaded through as (value, next) pairs instead of a cursor with a var field, so a parse cannot be left half-advanced by an early return.

The subset is named rather than implied. What is here is what a configuration file uses and what kite.toml needs:

back out in the same form they were read

\UXXXXXXXX, and literal '…' strings

literal for either, and dividing to reach one is a trap

What is not here, and would be wrong to guess at: dates and times. TOML's offset date-time, local date-time, date and time are four distinct types, and Kite has time.Instant and time.Date to map two of them onto — so the mapping is a decision about std/time's surface rather than about parsing, and it is left undone rather than half-done. A date in a document parses as the string it was written as, which is lossless and honest, and is stated here so nobody discovers it from a wrong answer.

Toml

enum Toml

A TOML value.

Recursive with no boxing annotation, because every Kite aggregate is already a GC reference.

parse

pub fn parse(input: str) -> (Toml, error)

The table a document holds, or an error saying where it went wrong.

The top level of a TOML document is always a table, which is the one way it differs from JSON at the root.

at

pub fn at(doc: Toml, path: str) -> Option<Toml>

The value at a dotted path, or nil.

toml.at(doc, "package.name") rather than three lookups and two matches, because reading a configuration file is the thing this module is for.

text_at

pub fn text_at(doc: Toml, path: str, fallback: str) -> str

The string at a path, or fallback if it is absent or is not a string.

int_at

pub fn int_at(doc: Toml, path: str, fallback: int) -> int

The integer at a path, or fallback.

float_at

pub fn float_at(doc: Toml, path: str, fallback: float) -> float

The float at a path, or fallback.

An integer answers too. TOML distinguishes 1 from 1.0 and a caller asking for a float has already said which it wants, so refusing to widen would fail on a configuration that simply wrote a round number.

bool_at

pub fn bool_at(doc: Toml, path: str, fallback: bool) -> bool

The boolean at a path, or fallback.

emit

pub fn emit(doc: Toml) -> str

A document, written back out.

Scalars first and tables afterwards, which is not a style preference: a key written after a [table] header belongs to that table, so a top-level key emitted after one would be read back into the wrong place. Emitting in this order is what makes parse(emit(doc)) give back doc.