TOML
The akurai-toml crate is a pure-std, zero-dependency parser for the slice of TOML the framework needs to declare data collections in backend/collections.toml. Like every crate in the workspace, it links no external crates and is #![forbid(unsafe_code)].
It parses a deliberately tight subset — just enough for collection config, done correctly. Anything outside the subset errors cleanly with a line number; the parser never panics on malformed input.
The Value type
Parsing produces an order-preserving value tree (a Vec of pairs, not a map, so the parsed schema reads the way it was written — and so we stay dependency-free):
pub enum Value {
Table(Vec<(String, Value)>),
Array(Vec<Value>),
Str(String),
Int(i64),
Float(f64),
Bool(bool),
}
The public API is a single function returning the top-level table:
pub fn parse(input: &str) -> Result<Value, TomlError>;
parse always returns Value::Table(_) on success. TomlError carries a message and the 1-based line where parsing gave up.
Convenience accessors mirror akurai-json: get(key), as_table(), as_array(), as_str(), as_i64(), as_f64(), as_bool().
Supported subset
- Key/value lines —
key = value. Bare keys areA-Za-z0-9_-. - Strings — basic strings
"..."with the escapes\",\\,\n,\t. - Integers — optional
+/-sign and_digit separators (1_000_000). - Floats — decimal point and/or exponent (
1.5,2.0e3). - Booleans —
true/false. - Arrays — inline
[a, b, c]. A trailing comma and newlines inside the
brackets are allowed, so arrays may span lines.
[table]headers — with dotted paths, e.g.[server.tls].[[array of tables]]headers — the key feature for collection config (see
below), with dotted paths, e.g. [[collection.field]].
- Dotted keys — both in headers and as bare keys (
a.b.c = 1) create the
intermediate tables.
- Comments —
#to end of line, whole-line or trailing. - Blank lines and arbitrary indentation — TOML ignores indentation; it is
only there for readability.
The array-of-tables model
A [[name]] header appends a new empty table to the array at name, creating the array on first use. Subsequent key/value lines (and nested [[name.child]] headers) write into that most recent element. This is what lets a collection own an ordered list of fields:
# a collection
[[collection]]
name = "posts"
[[collection.field]]
name = "title"
type = "text"
required = true
[[collection.field]]
name = "body"
type = "text"
embed = true
[[collection]]
name = "notes"
[[collection.field]]
name = "n"
type = "int"
parses to (in Value terms): a top-level table with one key collection, whose value is an Array of two tables. The first has name = "posts" and a field array of two tables (title, body); the second has name = "notes" and a field array of one table (n). Order is preserved throughout.
use akurai_toml::{parse, Value};
let doc = parse(src)?;
let collections = doc.get("collection").and_then(Value::as_array).unwrap();
assert_eq!(collections.len(), 2);
let title = collections[0].get("field").and_then(Value::as_array).unwrap()[0]
.get("name").and_then(Value::as_str);
assert_eq!(title, Some("title"));
Not supported
These error cleanly (with a line number) rather than parsing incorrectly:
- Multi-line basic strings (
"""...""") - Literal strings (
'...') - Datetimes
- Inline tables (
{ a = 1 }) - Non-decimal integers (
0xFF,0o17,0b101) inf/nanfloats- Unicode (
\uXXXX) and other escapes beyond\",\\,\n,\t
If the collection config ever needs one of these, extend the subset deliberately — and add a failing test first.