Expand description
An application’s own data file: a TOML document with a declared shape, which can hold arrays of tables and is never repaired behind the application’s back.
id = "api"
name = "Payments API"
created = "2026-09-18"
[[profile]]
name = "review"
added = "2026-09-18"
[[profile]]
name = "nightly"This is not Settings. Settings are the user’s preferences: they
fall back to defaults, they self-heal, and a value they cannot store is dropped. A document is
the application’s own file — a project, a profile, a record, a list of sources. It has no
defaults, it holds tables and arrays of tables, and nothing is ever written back: reading
a broken document reports it, and no .bak file is left behind either. Saving stays the
application’s own step, with atomic_write.
A Shape declares what the document holds. Reading gives a Document: the part that
could be read, and a located Diagnostic for everything that could not.
- A key of the declared type is read.
- A key the shape does not declare is a warning and is skipped.
- A value of another type is skipped: an error when the key is required, a warning when it is optional.
- A required key that is not there at all is an error, reported where its table starts.
- A syntax error is an error, and the rest of the file is still read.
Reading gives the valid part of a broken document rather than nothing, for the same reason
every other loader in the framework does: a file the user wrote by hand is usually wrong in
one place, and an application that can still name a project with one unreadable profile is
more use than one that opens nothing. The application decides what to do: the diagnostics say
what is wrong, and a required key that is missing reads as None.
use qframe::document::{Document, Shape, ValueKind};
let profile = Shape::new().required("name", ValueKind::text()).optional("added", ValueKind::text());
let shape = Shape::new()
.required("id", ValueKind::text())
.optional("name", ValueKind::text())
.entries("profile", profile);
let text = "id = \"api\"\nname = \"Payments API\"\n\n[[profile]]\nname = \"review\"\n\n[[profile]]\n";
let document = Document::parse("project.qcode", text, &shape);
assert_eq!(document.root().text("id"), Some("api"));
let names: Vec<&str> = document.root().entries("profile").iter().filter_map(|e| e.text("name")).collect();
assert_eq!(names, vec!["review"]);
assert_eq!(
document.diagnostics()[0].to_string(),
"project.qcode:7:1: error: `profile[1].name` is required and missing"
);Structs§
- Document
- A document read against a
Shape: the part that could be read, and a diagnostic for everything that could not. - Shape
- The shape of one table of a document: which keys it holds, which tables sit inside it and which of its keys carry an array of tables.
- Table
- One table of a document, read against its
Shape: the values it holds, the tables inside it and its arrays of tables. - Value
Kind - What one key of a
Shapemay hold, forShape::requiredandShape::optional.