feat: Add TOML marshalling API
This commit is contained in:
+58
-2
@@ -1,11 +1,13 @@
|
||||
// Package interpres is a dependency-free TOML parser for Go.
|
||||
//
|
||||
// interpres reads TOML documents into Go values using only the standard
|
||||
// library. It exposes a small, encoding/json-style API:
|
||||
// interpres reads and writes TOML documents using only the standard library.
|
||||
// It exposes a small, encoding/json-style API:
|
||||
//
|
||||
// var cfg Config
|
||||
// err := interpres.Unmarshal(data, &cfg)
|
||||
//
|
||||
// out, err := interpres.Marshal(cfg)
|
||||
//
|
||||
// or, for an untyped tree:
|
||||
//
|
||||
// tree, err := interpres.Parse(data)
|
||||
@@ -84,3 +86,57 @@ func (d *Decoder) Decode(data []byte, v any) error {
|
||||
dec.disallowUnknown = d.disallowUnknown
|
||||
return dec.decode(tree, v)
|
||||
}
|
||||
|
||||
// Marshaler is the interface implemented by types that can produce a custom
|
||||
// TOML representation of themselves. MarshalTOML returns a value that Marshal
|
||||
// then encodes as if the returned value had been passed in its place — useful
|
||||
// for emitting a Go type as a different TOML shape (for example, a struct as
|
||||
// an inline table or a primitive alias as a richer value).
|
||||
type Marshaler interface {
|
||||
MarshalTOML() (any, error)
|
||||
}
|
||||
|
||||
// Marshal returns the TOML 1.0 encoding of v.
|
||||
//
|
||||
// Marshal traverses v using reflection and applies the following rules:
|
||||
//
|
||||
// - The top-level value must be a struct or a 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; `-` skips). Anonymous (embedded) fields without
|
||||
// a tag are inlined.
|
||||
// - Maps use sorted keys for deterministic output.
|
||||
// - Slices and arrays of structs or maps become TOML arrays of tables; a
|
||||
// nil or empty array of tables is omitted (TOML forbids an empty `[[a]]`),
|
||||
// while other empty arrays emit as `key = []`.
|
||||
// - Other slices and arrays become TOML arrays.
|
||||
// - Scalars encode as TOML scalars: bool, int64, float64, string, time.Time
|
||||
// (offset date-time), and LocalDateTime/LocalDate/LocalTime (local
|
||||
// variants).
|
||||
// - Values implementing Marshaler are encoded by calling MarshalTOML and
|
||||
// using its result.
|
||||
// - nil pointer fields are omitted.
|
||||
//
|
||||
// Marshal cannot encode cyclic data structures — passing one will loop until
|
||||
// the stack overflows. The output is not guaranteed to be byte-identical to
|
||||
// the input that produced v: comments, whitespace, key order (for maps),
|
||||
// string quoting style, and the choice between `[table]` headers and inline
|
||||
// tables are not preserved.
|
||||
func Marshal(v any) ([]byte, error) {
|
||||
return NewEncoder().Marshal(v)
|
||||
}
|
||||
|
||||
// An Encoder encodes Go values into TOML.
|
||||
type Encoder struct{}
|
||||
|
||||
// NewEncoder returns an Encoder.
|
||||
func NewEncoder() *Encoder { return &Encoder{} }
|
||||
|
||||
// Marshal encodes v to TOML bytes. It is equivalent to calling Marshal with v.
|
||||
func (e *Encoder) Marshal(v any) ([]byte, error) {
|
||||
enc := newEncoder()
|
||||
if err := enc.encode(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return enc.bytes(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user