formats: std/toml #77
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
TOML on
Encode/Decodewith its tree.Source
Acceptance criteria
EncodeandDecodein the versions of the tabledocs/standard-library/Dependencies
None known.
Moved from the planning lists of the docs; the design record stays the specification.
[loop:torbscript] intake: in scope (author orion, label loop), sources ROADMAP.md format versions and ENCODING.md section 9, not a duplicate, no collision with a design record. TorbScript package on
Encode/Decode; the public test suite runs in forge CI; no seed impact expected. next: refine, waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z[loop:torbscript] claim refine by session:loop-torbscript-20261009 until 2026-10-10T00:30Z
[loop:torbscript] refine: ready.
Goal. A new package
std/toml: TOML as a format ofstd/encoding, written in TorbScript likestd/yaml/std/json.Tomlreads and writes anyEncode/Decodetype, andTomlValueis the tree of a document for a file nobody has a type for. Versions per the ROADMAP table: reads 1.0 and every later 1.x (the 0.x drafts are not supported), writes the current version unless the caller asks for an earlier one.Implements. ROADMAP part 3 ("Formats", the row
TOML | 1.0 and every later 1.x) and ENCODING.md section 9 (family "text tree", baseline, a naming option). No new design record: the decisions below go into the package page and a "built" note in the ROADMAP; ENCODING.md stays unchanged.Seed impact: none. New std package only: no syntax, no native, no driver flag, no std name the compiler looks up by string, and the compiler does not import
std/toml. One PR, no seed refresh.Size. One PR, two Conventional Commits (the first is large because the reader is one unit, but the tests are mostly one generated file):
feat(std/toml): read and write TOML 1.x as a tree and through Encode and Decodedocs(std/toml): add the package page and refresh the skillsFiles and directories touched.
std/toml/project.trb(name = "std/toml"; the workspace member globstd/*picks it up)std/toml/src/:lib.trb(public exports + package doc),toml.trb(Toml,TomlVersion),error.trb(TomlErrorwith line and column),value.trb(tree:TomlValue,TomlTable, date/time types),scanner.trb/parser.trb(text -> tree, TOML ABNF),writer.trb(tree -> text),encoder.trb(Encoderbuilding the tree),decoder.trb(tree ->Decoder, reusingValueDecoderofstd/encodingwhere it fits)std/toml/tests/:suite-cases.trb(generated, vendored),suite.test.trb,toml.test.trbdocs/standard-library/toml.md(new),docs/standard-library/index.md(one entry),docs/ROADMAP.md(part 3: "jsonandtomlexist")skills/torbscript-standard-library/**regenerated withbuild/release/torb docs skill docs skillsModel after
std/yaml(same file split, same page layout withtrb checkfragments,orderin the front matter after yaml/markdown).API (match yaml/json conventions).
Toml { naming: Naming = Unchanged, strict: Bool = false, version: TomlVersion = current }withencode<Value: Encode>(value): Result<String, TomlError>(a top-level value must be a table;Nonein a field is omitted;Noneinside an array is an error, because TOML has no null),decode<Value: Decode>(text): Result<Value, TomlError>,parse(text): Result<TomlValue, TomlError>,write(tree): String.TomlVersion { case Toml10, Toml11 }selects what the writer emits (1.0 output uses no 1.1-only syntax); the reader accepts the superset of every released 1.x grammar.TomlValuecases:String,Integer(Int64),Float(Float64),Boolean,OffsetDateTime,LocalDateTime,LocalDate,LocalTime,Array,Table(keys in document order). The tree does not keep comments (not required by the ROADMAP or this issue).TomlDate,TomlTime,TomlLocalDateTime,TomlOffsetDateTimevalue types owned bystd/toml(nanosecond precision, offset in minutes,show()gives the RFC 3339 text). They encode/decode as wrappers named by type (ENCODING.md wrapper rule), so a typed field can hold one;TomlOffsetDateTime.toTimestamp()converts toTimestamp. AStringfield reads the text of a date/time value.Decided by the loop (record).
[loop:torbscript] decided by the loop: date/time values are std/toml's own small value types, not a dependency on #111 (calendar types). Why: #111 is open and unrefined and TOML needs local date/time forms thatTimestampcannot hold; the package is self-contained and a bridge to #111's types is a follow-up once it lands.[loop:torbscript] decided by the loop: encode returns Result<String, TomlError>, not String. Why: TOML cannot express a top-level scalar or a null in an array, so writing can fail; a panic would break the PANICS.md rule.[loop:torbscript] decided by the loop: no Format<TomlError> impl and no framer in this issue. Why: a TOML file is one document, nothing in the acceptance criteria needs streaming; add it if a user needs it.[loop:torbscript] decided by the loop: the reader accepts the superset grammar of all released 1.x versions andversiononly controls writing. Why: the ROADMAP rule (read the old, write the current unless asked) and one grammar is smaller than two.Acceptance criteria (testable).
Toml().decode<T>/encoderound-trip records, nested records,List,Map<String, V>,Optionfields (omitted whenNone, default when absent), variants, andNaming.SnakeCase;strict: truerefuses unknown keys. Errors carry line and column.validcase of toml-test (https://github.com/toml-lang/toml-test, MIT) for the supported versions yields the suite's tagged JSON (compared numerically for floats,nan/infhandled), everyinvalidcase is refused. The cases are vendored as a generatedstd/toml/tests/suite-cases.trbwith the suite's MIT notice and the pinned release tag in the header, nothing hand-edited (same asstd/yaml/tests/suite-cases.trb).inf/nanhave tests of their own intoml.test.trbbeyond the suite where the suite is silent (typed decode, naming, strict, version option, date/time wrappers,toTimestamp).docs/standard-library/toml.mdexists, itstrb checkblocks pass, the front matter satisfiestorb docs check, the skills are regenerated (torb docs skill --checkclean).Test plan (forge CI, tier A,
.forgejo/workflows/gates.yml).torb format --check .,torb check .,manifest --check(newproject.trb),torb test --native std/toml/testsandtorb test std/toml/tests(VM) via the std/example package loop intools/gates.sh, the docs checks (docs check,docs skill --check, signature blocks of the std pages). Nothing runs locally in the loop; the implementer may runsh tools/gates.sh ain the worktree, and must keep the VM run of the suite inside the memory limit (split the generated cases into groups likestd/yamlif a single run is too slow). Tier B is not triggered (nocompiler/src/ir,compiler/src/backendorruntime/change).Implementer. sonnet / medium (std package and docs only). Not an owner question: nothing public-facing beyond the new package page, no cost, no account, no breaking change, nothing reserved by a design record.
next: implement
[loop:torbscript] claim implement by session:loop-torbscript-20261009 until 2026-10-10T04:40Z
[loop:torbscript] implement: PR #285 open, CI green (feat
a626a476, docsc06f0383).Tokens: roughly 2 sessions of one worker (about 1.5M tokens incl. suite generator, parser/writer and the CI round for the declarations gate); exact figures are in the loop budget report.
next: waiting (merge gate review of PR #285)