feat: scaffold interpres project with TOML parser and CI
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// 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:
|
||||
//
|
||||
// var cfg Config
|
||||
// err := interpres.Unmarshal(data, &cfg)
|
||||
//
|
||||
// or, for an untyped tree:
|
||||
//
|
||||
// tree, err := interpres.Parse(data)
|
||||
//
|
||||
// A Decoder allows strict decoding that rejects keys without a matching
|
||||
// struct field, mirroring (*json.Decoder).DisallowUnknownFields.
|
||||
package interpres
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A SyntaxError describes a malformed TOML document, including the 1-based
|
||||
// line on which the problem was detected.
|
||||
type SyntaxError struct {
|
||||
Line int
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *SyntaxError) Error() string {
|
||||
return fmt.Sprintf("interpres: line %d: %s", e.Line, e.Msg)
|
||||
}
|
||||
|
||||
// Parse decodes a TOML document into a nested map[string]any.
|
||||
//
|
||||
// Values are mapped to Go types as follows: strings to string, integers to
|
||||
// int64, floats to float64, booleans to bool, date-times to time.Time, arrays
|
||||
// to []any, and tables (including inline tables) to map[string]any.
|
||||
func Parse(data []byte) (map[string]any, error) {
|
||||
if !utf8.Valid(data) {
|
||||
return nil, &SyntaxError{Line: 1, Msg: "input is not valid UTF-8"}
|
||||
}
|
||||
p := &parser{src: []rune(string(data)), line: 1}
|
||||
return p.parse()
|
||||
}
|
||||
|
||||
// Unmarshal parses a TOML document and stores the result in the value pointed
|
||||
// to by v. v is typically a pointer to a struct or to a map[string]any.
|
||||
//
|
||||
// Struct 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.
|
||||
func Unmarshal(data []byte, v any) error {
|
||||
tree, err := Parse(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return newDecoder().decode(tree, v)
|
||||
}
|
||||
|
||||
// A Decoder decodes a TOML document into a Go value with configurable
|
||||
// strictness.
|
||||
type Decoder struct {
|
||||
disallowUnknown bool
|
||||
}
|
||||
|
||||
// NewDecoder returns a Decoder.
|
||||
func NewDecoder() *Decoder { return &Decoder{} }
|
||||
|
||||
// DisallowUnknownFields causes Decode to return an error when the document
|
||||
// contains a key with no matching destination struct field.
|
||||
func (d *Decoder) DisallowUnknownFields() *Decoder {
|
||||
d.disallowUnknown = true
|
||||
return d
|
||||
}
|
||||
|
||||
// Decode parses data and stores the result in the value pointed to by v,
|
||||
// honouring the decoder's strictness settings.
|
||||
func (d *Decoder) Decode(data []byte, v any) error {
|
||||
tree, err := Parse(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec := newDecoder()
|
||||
dec.disallowUnknown = d.disallowUnknown
|
||||
return dec.decode(tree, v)
|
||||
}
|
||||
Reference in New Issue
Block a user