std/toml
Toml reads and writes any Encode/Decode type as TOML 1.0 or 1.1, and TomlValue is the tree of a document, with date and time values that keep their nanoseconds and their offset.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
Die generierte Referenz von std/toml zeigt jede öffentliche Deklaration mit Signatur, Doc-Kommentar und Beispielen.
std/toml is TOML as a format of std/encoding, written in TorbScript. Toml reads a document into any
Decode type and writes any Encode value, and TomlValue is the tree of a document, for one whose shape is not known
ahead of time. The reader takes every released 1.x - 1.0 and 1.1 - and passes the public
toml-test suite for both, which is vendored with its notice in
std/toml/tests; whatever the reader accepts as valid, the writer writes back as an equal tree.
Import#
use Toml, TomlVersion, TomlError from "std/toml"
use TomlValue, TomlEntry from "std/toml"
use TomlOffsetDateTime, TomlLocalDateTime, TomlDate, TomlTime from "std/toml"use Toml from "std/toml"
type Service {
name: String
replicas: Int = 1
ports: List<Int> = []
}
const toml = Toml()
match toml.decode<Service>("name = \"web\"\nports = [80, 443]\n") {
Ok(service) => {
match toml.encode(service) {
Ok(text) => print text
Fail(problem) => print "Not writable: {problem}"
}
}
Fail(problem) => print "Rejected: {problem}"
}replicas is not in the document, so it takes its default.
Declarations#
Toml#
type Toml {
naming: Naming = Naming.Unchanged
strict: Bool = false
version: TomlVersion = TomlVersion.Toml11
fn encode<Value: Encode>(value: Value): Result<String, TomlError>
fn decode<Value: Decode>(text: String): Result<Value, TomlError>
fn parse(text: String): Result<TomlValue, TomlError>
fn value<Value: Encode>(value: Value): Result<TomlValue, TomlError>
fn write(tree: TomlValue): String
}A Toml is the format with its options. naming spells every field name and strict makes a key of the document that
no type asked for an error, as they do for std/json and std/yaml. Toml has no Format
implementation and no framer: a TOML document is one table that is read whole, not a stream of items.
A document is a table. encode accepts a record or a map and refuses any other value with a TomlError, since a
number or a list is not a TOML document. TOML has no null: a field that holds None is left out, a key the document
does not have reads as None or as the field's default, and None inside a list is an error. A number beyond 64 bits
is an error as well, and bytes are written as a string of base64. A record that announces no field is its one value, a
case without fields is its name and a case with fields a table of one entry, its name.
decode reads one document. A failure is a TomlError: for text that is not TOML it has the line and the column, and
for a document that does not fit the type it has the chain of fields it went wrong in.
line 3, column 9: a value was expected here, and the line ends
ports[1]: a whole number is needed, not "http"parse reads the tree, write writes a tree back, and value is the tree an Encode value is written as. A
document is rejected where it defines a key or a table twice, extends a table that an inline table or an earlier
section closed, or gives an array of tables the name of a table.
TomlVersion#
type TomlVersion {
case Toml10
case Toml11
}version chooses what the writer may use, and nothing else: the reader accepts what is valid in either version. The
two differ in how a control character of a string is written, \uHHHH for Toml10 and \e or \xHH for Toml11, the
default. A document written for Toml10 can be read by every TOML 1.x reader; one for Toml11 needs a reader of 1.1.
The reader accepts what 1.1 adds in every document: an inline table over several lines and with a trailing comma, a time
without seconds, and the escapes \e and \xHH. A byte order mark in front of the document is skipped.
TomlValue#
type TomlValue with Show, Equals {
case String(value: String)
case Integer(value: Int)
case Float(value: Float64)
case Boolean(value: Bool)
case OffsetDateTime(value: TomlOffsetDateTime)
case LocalDateTime(value: TomlLocalDateTime)
case LocalDate(value: TomlDate)
case LocalTime(value: TomlTime)
case Array(items: List<Self>)
case Table(entries: List<TomlEntry>)
fn at(key: String): Self?
fn items(): List<Self>
fn entries(): List<TomlEntry>
fn isTable(): Bool
fn updated(key: String, value: Self): Self
fn equals(other: Self): Bool
fn show(): String
}
type TomlEntry with Show, Equals {
key: String
value: TomlValue
fn show(): String
}The tree of a document: what it says, in the order it says it. A table keeps its keys in the order of the document, and
the tree does not keep comments, the way a table was split into sections, or the kind of quotes a string used.
equals ignores the order of the keys of a table - TOML does not give it a meaning - and counts nan as equal to
nan, so a document and what the writer wrote of it are equal.
at(key) is the value of a key of a table, items() and entries() are the elements of an array and the entries of a
table (empty for any other value), and updated(key, value) is a table with one value set, kept in its place or added
at the end.
use Toml, TomlValue from "std/toml"
const toml = Toml()
match toml.parse("[server]\nhost = \"example.org\"\nport = 8080\n") {
Ok(tree) => {
const server = tree.at("server") ?? TomlValue.Table([])
print server.at("port")
print toml.write(tree.updated("title", TomlValue.String("demo")))
}
Fail(problem) => print "Rejected: {problem}"
}Dates and times#
type TomlDate with Show, Equals, Compare {
year: Int
month: Int
day: Int
static fn parse(text: String): Result<Self, DecodeError>
fn daysSinceEpoch(): Int
fn compare(other: Self): Ordering
fn show(): String
}
extend TomlDate with Encode, Decode
type TomlTime with Show, Equals, Compare {
hour: Int
minute: Int
second: Int = 0
nanosecond: Int = 0
static fn parse(text: String): Result<Self, DecodeError>
fn nanosecondsOfDay(): Int
fn compare(other: Self): Ordering
fn show(): String
}
extend TomlTime with Encode, Decode
type TomlLocalDateTime with Show, Equals, Compare {
date: TomlDate
time: TomlTime
static fn parse(text: String): Result<Self, DecodeError>
fn compare(other: Self): Ordering
fn show(): String
}
extend TomlLocalDateTime with Encode, Decode
type TomlOffsetDateTime with Show, Equals {
dateTime: TomlLocalDateTime
offsetMinutes: Int = 0
static fn parse(text: String): Result<Self, DecodeError>
fn toTimestamp(): Timestamp?
fn show(): String
}
extend TomlOffsetDateTime with Encode, DecodeTOML has four values for a point in time, and each is a type of its own so a field says which one it wants: a date
(1979-05-27), a time (07:32:00.5), a date and time without an offset (1979-05-27T07:32:00) and a date and time
with one (1979-05-27T07:32:00Z or 1979-05-27T00:32:00-07:00). They keep nanoseconds and the offset in minutes, and
show() is their RFC 3339 text. parse reads that text, with a space instead of the T too. A date that is not on
the calendar, such as February 30, is an error.
TomlOffsetDateTime.toTimestamp() is the point in time as a Timestamp of std/time, and None for one
beyond what a Timestamp holds.
In a document the four are TOML's own date and time values, not strings. They encode and decode as wrappers named by
their type, so a format that has no such value, JSON for one, writes the RFC 3339 text. A String field reads the
text of a date or time value as it was written.
use Toml, TomlOffsetDateTime from "std/toml"
type Release {
name: String
at: TomlOffsetDateTime
}
match Toml().decode<Release>("name = \"1.0\"\nat = 1979-05-27T00:32:00.5-07:00\n") {
Ok(release) => {
print release.at.show()
print release.at.toTimestamp()
}
Fail(problem) => print "Rejected: {problem}"
}TomlError#
type TomlError with Show, Error {
static fn syntax(line: Int, column: Int, message: String): Self
static fn decodeFailed(cause: DecodeError, line: Int = 0): Self
static fn unwritable(message: String): Self
fn isSyntaxError(): Bool
fn line(): Int
fn column(): Int
fn message(): String
fn show(): String
fn cause(): Error?
}What went wrong: text that is not TOML (syntax, with its line and column counted from 1), a document that does not fit
the type (decodeFailed, with the DecodeError that names the field chain) or a value that TOML cannot say
(unwritable). line() and column() are 0 where the problem belongs to none.
TomlEncoder#
type TomlEncoder with Encoder {
naming: Naming = Naming.Unchanged
fn result(): Result<TomlValue, TomlError>
var fn nothing()
var fn bool(value: Bool)
var fn int(value: Int64)
var fn unsigned(value: UInt64)
var fn float(value: Float64)
var fn decimal(value: Decimal)
var fn string(value: String)
var fn bytes(value: Bytes)
var fn sequence(length: Int?)
var fn map(length: Int?)
var fn record(typeName: String)
var fn variant(typeName: String, name: String)
var fn field(name: String)
var fn finish()
}TomlEncoder is the Encoder behind encode and value, exported for a format that builds on it. A value is
encoded into it, and result() is the tree, or the first thing that TOML cannot say.
Related#
- std/encoding -
Encode,DecodeandNaming, whichTomlimplements. - std/json - the same shape for JSON.
- std/yaml - the same shape for YAML.
- The standard library - the other packages.