toml

package module
v0.0.0-...-c6027db Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause Imports: 8 Imported by: 0

README

go-ruby-toml/toml

toml — go-ruby-toml

Docs License Go Coverage

A pure-Go (no cgo) TOML v1.0.0 parser and generator for the Ruby value model, faithful to the toml-rb gem. Parse turns a TOML document into a Ruby Hash (an insertion-ordered *Map); Dump renders such a value back to a TOML string — so it is the deterministic, interpreter-independent core of TomlRB.parse / TomlRB.dump, without any Ruby runtime.

It is the TOML backend for go-embedded-ruby, but is a standalone, reusable module with no dependency on the Ruby runtime — a sibling of go-ruby-yaml (the Psych engine), go-ruby-regexp (the Onigmo engine) and go-ruby-erb (the ERB compiler).

What it is — and isn't. Lexing and parsing TOML (the bare/quoted/dotted key grammar, the four string styles, integers/floats, the RFC 3339 date/time shapes, arrays, inline tables, [table] and [[array of tables]] headers, and the redefinition rules) is fully deterministic and needs no interpreter, so it lives here as pure Go. Binding the result to live Ruby objects — materialising a Time in the host's zone, wrapping a Hash — is the host's job; this library hands back a small, explicit value model the host maps to and from its own objects.

Features

Faithful port of toml-rb's parse + dump, validated against the gem on every supported platform:

  • Keys — bare (A-Za-z0-9_-), basic-quoted, literal-quoted, and dotted (a.b.c), in key/value lines, table headers, and inline tables.
  • Strings — basic ("…"), literal ('…'), multiline basic ("""…""") and multiline literal ('''…'''), with the \n \t \r \" \\ \b \f \e escapes, \uXXXX / \UXXXXXXXX and the \xHH byte escape, the opening-newline trim, and the line-ending-backslash whitespace trim.
  • Numbers — decimal / 0x hex / 0o octal / 0b binary integers with _ separators (leading-zero and bad-separator rejection), and floats with fractions, exponents, and inf / -inf / nan.
  • Date/time — offset date-time, local date-time, local date, and local time (RFC 3339), kept as an explicit value model (OffsetDateTime, LocalDateTime, LocalDate, LocalTime) the host maps to Time / Date.
  • Arrays — mixed-type, nested, with newlines, comments, and trailing commas.
  • Tables[table], [a.b.c] super-tables (out-of-order allowed), inline { … } tables, and [[array of tables]] (including nested), with the full redefinition / overwrite error rules (TomlRB::ValueOverwriteError).
  • DumpDump(*Map | map[string]any) emits scalar pairs, then [table] sections, then [[array]] sections, recursively — round-tripping Parse.

CGO-free, dependency-free, 100% test coverage, gofmt + go vet clean, and green across the six 64-bit Go targets (amd64, arm64, riscv64, loong64, ppc64le, s390x) on Linux, macOS, and Windows.

Install

go get github.com/go-ruby-toml/toml

Usage

package main

import (
	"fmt"

	"github.com/go-ruby-toml/toml"
)

func main() {
	doc, _ := toml.Parse(`
title = "TOML Example"

[server]
ip = "10.0.0.1"
ports = [8000, 8001]

[[product]]
name = "Hammer"
`)
	// Parse returns an insertion-ordered *toml.Map (a Ruby Hash).
	srv, _ := doc.Get("server")
	ip, _ := srv.(*toml.Map).Get("ip")
	fmt.Println(ip) // 10.0.0.1

	// Dump renders a value tree back to TOML (TomlRB.dump).
	m := toml.NewMap()
	m.Set("name", "weft")
	m.Set("ports", []any{80, 443})
	out, _ := toml.Dump(m)
	fmt.Print(out)
	// name = "weft"
	// ports = [80, 443]
}

Ruby value model

Parse returns an any drawn from a small, fixed set of Go types, so a host can map its own object graph to and from this package:

TOML Go (Parse returns) Ruby (rbgo maps to)
string string String
integer int64 Integer
float / inf / nan float64 Float
boolean bool true / false
array []any Array
table / inline table *toml.Map (ordered) Hash
offset date-time toml.OffsetDateTime Time
local date-time toml.LocalDateTime Time (host zone)
local date toml.LocalDate Time at 00:00 (host zone)
local time toml.LocalTime Time on 1970-01-01

toml-rb collapses every TOML date/time onto Ruby's Time, projecting the offset-less variants onto the host's local zone. This package keeps the faithful TOML distinction (local vs. offset, with no host-zone guessing) so the host applies its zone exactly once when it materialises a Ruby Time. Dump also accepts Go's time.Time and map[string]any (emitted in sorted-key order).

API

// Parse parses a TOML v1.0.0 document into a Ruby Hash (TomlRB.parse / TOML.parse).
func Parse(s string) (*Map, error)

// LoadFile reads and parses a file (TomlRB.load_file / TOML.load_file).
func LoadFile(path string) (*Map, error)

// Dump renders a *Map or map[string]any to a TOML string (TomlRB.dump).
func Dump(v any) (string, error)

type Map struct { /* insertion-ordered Hash */ }
func NewMap() *Map
func (m *Map) Set(key string, val any)
func (m *Map) Get(key string) (any, bool)
func (m *Map) Pairs() []Pair
func (m *Map) Len() int

type OffsetDateTime struct{ Time time.Time }
type LocalDateTime  struct{ Year, Month, Day, Hour, Minute, Second, Nanosecond int }
type LocalDate      struct{ Year, Month, Day int }
type LocalTime      struct{ Hour, Minute, Second, Nanosecond int }

type ParseError     struct{ Msg string; Line, Col, Offset int } // TomlRB::ParseError
type OverwriteError struct{ Key string }                        // TomlRB::ValueOverwriteError

Conformance notes

  • Validated against toml-rb 4.x with a differential oracle (a corpus and the canonical TOML spec example are parsed both here and by the gem, and the canonicalised results are compared); rejected documents are cross-checked too.
  • Where toml-rb is laxer than the TOML v1.0.0 spec (e.g. it accepts a decimal integer with a redundant leading zero such as 01), this library follows the spec and rejects it; the divergent cases are skipped in the oracle.
  • A run of more than three quotes closing a multiline basic string is consumed the way toml-rb does ("""""""""""").

Tests & coverage

The suite pairs deterministic, ruby-free tests (which alone hold coverage at 100%, so the qemu cross-arch and Windows lanes pass the gate) with a differential toml-rb oracle that runs on the ubuntu/macOS lanes (skipped where the gem is absent). The oracle scripts $stdout.binmode so Windows text-mode never pollutes the bytes.

COVERPKG=$(go list ./... | paste -sd, -)
go test -race -coverpkg="$COVERPKG" -coverprofile=cover.out ./...
go tool cover -func=cover.out | tail -1   # 100.0%

License

BSD-3-Clause — see LICENSE. Copyright the go-ruby-toml/toml authors.

WebAssembly

Being pure Go (CGO=0), this library also compiles to WebAssembly — both GOOS=js GOARCH=wasm (browser / Node.js) and GOOS=wasip1 GOARCH=wasm (WASI). CI builds both targets on every push, alongside the six 64-bit native/qemu arches.

GOOS=js     GOARCH=wasm go build ./...   # browser / Node
GOOS=wasip1 GOARCH=wasm go build ./...   # WASI (wasmtime, wasmer, wasmedge, …)

Documentation

Overview

Package toml is a pure-Go (CGO-free) TOML v1.0.0 parser and generator for the Ruby value model, faithful to the toml-rb gem's semantics. Parse turns a TOML document into a Ruby Hash (an insertion-ordered *Map); Dump renders such a value back to a TOML string, so it is the deterministic, interpreter-independent core of toml-rb's TomlRB.parse / TomlRB.dump — without any Ruby runtime.

Ruby value model

A parsed document is an [any] drawn from a small, fixed set of Go types so a host (such as go-embedded-ruby) can map its own object graph to and from this package:

TOML                      Go (Parse returns)        Ruby (rbgo maps to)
----                      ------------------        -------------------
string                    string                    String
integer                   int64                     Integer
float / inf / nan         float64                   Float
boolean                   bool                      true / false
array                     []any                     Array
table / inline table      *Map (insertion order)    Hash
offset date-time          OffsetDateTime            Time
local date-time           LocalDateTime             Time
local date                LocalDate                 Time (00:00, local)
local time                LocalTime                 Time (1970-01-01, local)

toml-rb collapses every TOML date/time onto Ruby's Time using the host's local zone for the offset-less variants; this package keeps the faithful TOML datetime model (an explicit local/offset distinction with no host-zone guessing) so the host applies its own zone exactly once when it materialises a Ruby Time. Dump accepts these shapes plus Go's time.Time.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dump

func Dump(v Value) (string, error)

Dump renders a Ruby value (a *Map or Go map for the document root) to a TOML v1.0.0 string, matching TomlRB.dump. A value outside the supported model returns an error rather than panicking.

Types

type LocalDate

type LocalDate struct {
	Year, Month, Day int
}

LocalDate is a TOML local date (`YYYY-MM-DD`).

func (LocalDate) String

func (d LocalDate) String() string

String renders a LocalDate as YYYY-MM-DD.

type LocalDateTime

type LocalDateTime struct {
	Year, Month, Day     int
	Hour, Minute, Second int
	Nanosecond           int
}

LocalDateTime is a TOML local date-time (RFC 3339 with no offset). The fields are wall-clock components with no zone; the host supplies the zone when it maps the value to a Ruby Time.

func (LocalDateTime) String

func (d LocalDateTime) String() string

String renders a LocalDateTime in RFC 3339 (no offset).

type LocalTime

type LocalTime struct {
	Hour, Minute, Second int
	Nanosecond           int
}

LocalTime is a TOML local time (`HH:MM:SS[.fff]`).

func (LocalTime) String

func (t LocalTime) String() string

String renders a LocalTime as HH:MM:SS[.fff].

type Map

type Map struct {
	// contains filtered or unexported fields
}

Map is an insertion-ordered Ruby Hash. Parse returns tables and inline tables as *Map so key order round-trips; Dump accepts *Map or a plain Go map (emitted in sorted key order for determinism).

func LoadFile

func LoadFile(path string) (*Map, error)

LoadFile reads path and parses it as a TOML document, matching TomlRB.load_file / TOML.load_file.

func NewMap

func NewMap() *Map

NewMap returns an empty ordered Map.

func Parse

func Parse(s string) (*Map, error)

Parse parses a TOML v1.0.0 document into a Ruby Hash (an insertion-ordered *Map), matching TomlRB.parse / TOML.parse. A syntax error returns a *ParseError; a duplicate key returns a *OverwriteError.

func (*Map) Get

func (m *Map) Get(key string) (Value, bool)

Get returns the value for key and whether it was present.

func (*Map) Len

func (m *Map) Len() int

Len reports the number of entries.

func (*Map) Pairs

func (m *Map) Pairs() []Pair

Pairs returns the entries in insertion order. The slice must not be mutated.

func (*Map) Set

func (m *Map) Set(key string, val Value)

Set inserts or replaces the entry for key, preserving first-insertion order.

type OffsetDateTime

type OffsetDateTime struct {
	Time time.Time
}

OffsetDateTime is a TOML offset date-time (RFC 3339 with a `Z` or `±hh:mm` suffix). It is a thin alias over time.Time, which already carries the offset.

type OverwriteError

type OverwriteError struct {
	Key string
}

OverwriteError reports a key defined more than once — the condition toml-rb raises as TomlRB::ValueOverwriteError. Key is the offending key path component.

func (*OverwriteError) Error

func (e *OverwriteError) Error() string

Error renders the toml-rb message verbatim.

type Pair

type Pair struct {
	Key string
	Val Value
}

Pair is one entry of an ordered mapping.

type ParseError

type ParseError struct {
	Msg    string
	Line   int
	Col    int
	Offset int
}

ParseError reports a TOML syntax error. Line and Col are 1-based positions of the offending byte; Offset is its 0-based index in the document.

func (*ParseError) Error

func (e *ParseError) Error() string

Error renders the message with its source position, mirroring the location detail TomlRB::ParseError carries.

type Value

type Value = any

Value is the interface satisfied by every value this package handles. It is purely documentary — the public API uses any — but a host may use it to constrain its own adapters.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL