petrbalvin a73d3097d0
Test / vet (push) Successful in 39s
Release / release (push) Successful in 15s
Test / test (push) Successful in 1m15s
Test / toml-test (push) Successful in 42s
fix(ci): install gcc for -race on fedora runner
2026-07-26 18:46:35 +02:00
2026-07-26 18:37:36 +02:00
2026-06-26 20:12:15 +02:00
2026-06-26 20:12:15 +02:00
2026-06-26 20:12:15 +02:00
2026-06-26 20:12:15 +02:00
2026-07-26 18:37:36 +02:00
2026-06-26 20:12:15 +02:00
2026-07-26 18:37:36 +02:00

interpres

A dependency-free TOML 1.0 parser for Go — standard library only, no third-party modules. Passes the entire toml-test suite (185 valid and 371 invalid cases).

interpres (Latin for interpreter) reads TOML documents into Go values with a small, encoding/json-style API. It is built for embedding in zero-dependency Go programs that still want their configuration in TOML.

Install

go get sourcedock.dev/petrbalvin/interpres

Requires Go 1.26 or newer. The module imports only the standard library.

Usage

Decode into a struct

package main

import (
	"fmt"

	"sourcedock.dev/petrbalvin/interpres"
)

type Config struct {
	Title  string `toml:"title"`
	Server struct {
		Host string `toml:"host"`
		Port int    `toml:"port"`
	} `toml:"server"`
}

func main() {
	data := []byte(`
title = "example"

[server]
host = "127.0.0.1"
port = 9090
`)

	var cfg Config
	if err := interpres.Unmarshal(data, &cfg); err != nil {
		panic(err)
	}
	fmt.Printf("%+v\n", cfg)
}

Encode from a struct

out, err := interpres.Marshal(cfg)
if err != nil {
    panic(err)
}
fmt.Println(string(out))

writes the same struct back to TOML:

title = "example"

[server]
host = "127.0.0.1"
port = 9090

Untyped tree

tree, err := interpres.Parse(data)   // []byte → map[string]any
out, err := interpres.Marshal(tree)  // map[string]any → []byte

Custom encoding

Types that need a non-default TOML shape can implement Marshaler:

type Port int

func (p Port) MarshalTOML() (any, error) {
    return int64(p), nil
}

The returned value is encoded just like any other value passed to Marshal, which means it can be any type Marshal itself understands.

Strict decoding

Reject keys that have no matching struct field — useful for catching typos in configuration files:

err := interpres.NewDecoder().
	DisallowUnknownFields().
	Decode(data, &cfg)

Struct mapping

Fields are matched to TOML keys by the toml:"name" tag, or by a case-insensitive match on the field name when no tag is present. A tag of "-" skips the field.

TOML value Go type (untyped tree)
string string
integer int64
float float64
boolean bool
offset date-time time.Time
local date-time LocalDateTime
local date LocalDate
local time LocalTime
array []any
table / inline table map[string]any
array of tables []map[string]any

When decoding into a struct, these map onto the destination's concrete types (any integer/unsigned/float width, slices, nested structs, and map[string]T).

Encoding

Marshal produces valid TOML 1.0 from any struct or map[string]V value, applying these rules:

  • The top-level value must be a struct or map[string]V. Pointers are followed; a nil top-level pointer is an error.
  • Struct fields are matched by toml:"name" tag (case-insensitive fallback to field name; toml:"-" skips). Anonymous (embedded) fields without a tag are inlined.
  • Maps emit keys in sorted order for deterministic output.
  • Output is grouped by kind at every level: scalars come first, then sub-tables, then arrays of tables. Within each group the order matches struct field declaration order (or, for maps, sorted key order). This means in TOML terms a struct that mixes scalars and sub-tables always lays out scalars at the top of the section followed by the table headers — there is no way to interleave them and still produce a document that re-parses to the same tree.
  • Slices and arrays of structs or maps become [[a]] arrays of tables. Empty or nil arrays of tables are omitted (TOML forbids an empty [[a]]); empty arrays of scalars emit as key = [].
  • Other slices and arrays become TOML arrays, including mixed-type []any.
  • Scalars map to TOML scalars: bool, int64, float64, string, time.Time (offset date-time), and the local variants (LocalDateTime, LocalDate, LocalTime).
  • Strings are always emitted as basic "..." strings with the escapes TOML requires (\", \\, control characters as \uXXXX).
  • Keys are emitted as bare keys when they match [A-Za-z0-9_-]+, quoted otherwise.
  • Floats always carry a . or an exponent (so 1 is always emitted as 1.0), which preserves the distinction between an integer-typed value and a float-typed value across a MarshalParse round-trip.
  • Values implementing Marshaler are encoded by calling MarshalTOML and using its result.
  • nil pointer fields are omitted.

Marshal cannot encode cyclic data structures. The output is not guaranteed to be byte-identical to any TOML document that produced the input value: comments, whitespace, key order (for maps), the choice between [table] headers and inline tables, and the basic-vs-literal quoting style are not preserved. The emitted document is, however, guaranteed to be re-parsable by interpres.Parse back into an equivalent value tree.

TOML 1.0 support

interpres implements the full TOML 1.0 grammar:

  • Comments, and bare / quoted / dotted keys.
  • Tables [a.b] and arrays of tables [[a]].
  • Basic and literal strings, including multiline (""" / ''') with escape sequences (\n, \t, \uXXXX, \UXXXXXXXX, line-ending backslash).
  • Integers in decimal, hex (0x), octal (0o), and binary (0b) with _ separators; floats with exponents and inf / nan.
  • Booleans, offset/local date-times, dates, and times.
  • Arrays (multiline, mixed types) and inline tables.

Invalid documents are rejected per the specification (malformed numbers and floats, control characters, non-UTF-8 input, out-of-range escapes, table and inline-table redefinitions, and more).

Compliance

The parser is verified against the official toml-test suite via cmd/interpres-decode:

go build -o interpres-decode ./cmd/interpres-decode
toml-test ./interpres-decode

License

MIT — see LICENSE. Copyright © 2026 Petr Balvín

S
Description
A dependency-free TOML 1.0 parser for Go — standard library only.
Readme MIT
78 KiB
v1.1.1
Latest
2026-07-26 16:46:40 +00:00
Languages
Go 98.9%
Just 1.1%