Files
interpres/README.md
T

173 lines
4.6 KiB
Markdown
Raw Normal View History

2026-08-19 18:44:00 +02:00
# interpres
A TOML 1.1 parser and encoder for Go, written with the standard library
alone. `interpres` (Latin for *interpreter*) gives zero-dependency
2026-09-17 22:06:26 +02:00
programs an `encoding/json`-style API for reading and writing TOML, and passes
the entire official [toml-test](https://github.com/toml-lang/toml-test) suite:
214 valid and 467 invalid cases, zero failures.
2026-08-19 18:44:00 +02:00
## Features
- **Full TOML 1.1**: bare, quoted and dotted keys; tables and arrays of
2026-09-17 22:06:26 +02:00
tables; basic and literal strings including multiline, with the 1.1 `\e` and
`\xHH` escapes; integers in the four radixes with `_` separators; floats with
exponents, `inf` and `nan`; booleans; the four date-time kinds, seconds
optional as of 1.1; arrays and inline tables, multi-line as of 1.1.
2026-08-19 18:44:00 +02:00
- **Decoding and encoding**: `Parse` for an untyped tree, `Unmarshal` and
`Marshal` for structs and maps, mirroring `encoding/json`.
- **Strict decoding**: `NewDecoder().DisallowUnknownFields()` rejects keys that
match no destination field, at every struct depth.
- **Custom types**: `Marshaler` and `Unmarshaler` let a type control its own
TOML representation in both directions, and `encoding.TextMarshaler` and
`TextUnmarshaler` are honoured by default, so `net.IP`, `time.Duration` and
user types with text methods need no configuration.
2026-08-19 18:44:00 +02:00
- **Cancellation**: every entry point has a `*Context` sibling that honours a
`context.Context`.
- **Configurable emission**: `Encoder` options for declaration-order output,
omitting empty arrays, and literal multiline strings.
## Install
As a library:
```sh
2026-09-19 00:14:39 +02:00
go get sourcedock.dev/petrbalvin/interpres/v2
2026-08-19 18:44:00 +02:00
```
2026-09-17 19:41:22 +02:00
Requires Go 1.27.1 or newer. The module imports only the standard library.
2026-08-19 18:44:00 +02:00
## Quick start
```sh
git clone https://sourcedock.dev/petrbalvin/interpres.git
cd interpres
just example
```
`just example` runs the tour in `examples/basic`: it decodes an embedded
document into a struct, prints it, and re-encodes it under both `Encoder`
layouts.
## Usage
### Decode into a struct
```go
type Config struct {
Title string `toml:"title"`
Server struct {
Host string `toml:"host"`
Port int `toml:"port"`
} `toml:"server"`
}
var cfg Config
err := interpres.Unmarshal(data, &cfg)
```
Fields match by the `toml:"name"` tag, or by the lower-cased field name when no
tag is present; `toml:"-"` skips a field. `Parse` returns the untyped
`map[string]any` tree instead, and `UnmarshalContext` accepts a context.
### Encode from a struct
```go
out, err := interpres.Marshal(cfg)
```
writes:
```toml
title = "example"
[server]
host = "127.0.0.1"
port = 9090
```
Tables are laid out scalars first, then sub-tables, then arrays of tables,
which is the layout that re-parses to the same tree.
### Strict decoding
```go
err := interpres.NewDecoder().
DisallowUnknownFields().
Decode(data, &cfg)
```
A key with no matching field becomes an error instead of a silent drop.
### Custom types
```go
type Port int
func (p Port) MarshalTOML() (any, error) {
return int64(p), nil
}
type IP struct{ net.IP }
func (ip *IP) UnmarshalTOML(data any) error {
s, ok := data.(string)
if !ok {
return fmt.Errorf("ip: not a string")
}
ip.IP = net.ParseIP(s)
return nil
}
```
The value `MarshalTOML` returns is encoded in place of the receiver;
`UnmarshalTOML` receives the parsed value verbatim.
### Encoder options
```go
out, err := interpres.NewEncoder().
GroupByKind(false). // preserve declaration order
OmitEmptyArrays(). // skip empty scalar arrays
UseLiteralMultiline(80). // long multi-line strings as literal blocks
Marshal(cfg)
```
### Cancellation
```go
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
out, err := interpres.MarshalContext(ctx, cfg)
```
`ParseContext`, `UnmarshalContext`, `(*Decoder).DecodeContext` and
`(*Encoder).MarshalContext` follow the same pattern.
The full rules for field matching, numeric conversion and emission live in
[docs/API.md](docs/API.md).
## Development
```sh
just build # compile bin/interpres-decode
just test # the suite, with the 80 percent coverage floor
just toml-test # the official compliance suite, needs toml-test on PATH
just fmt # gofmt in place
```
See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the full workflow, and
[CONTRIBUTING.md](CONTRIBUTING.md) for how to contribute.
## Documentation
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): components and data flow
- [docs/API.md](docs/API.md): the API reference, decoding and encoding rules
- [docs/CLI.md](docs/CLI.md): the interpres-decode toml-test adapter and validator
2026-08-19 18:44:00 +02:00
## Licence
MIT. See [LICENSE](LICENSE).
Copyright © 2026 [Petr Balvín](https://petrbalvin.org)