mox/vendor/github.com/mjl-/sconf/sconf.go
Mechiel Lukkien cb229cb6cf
mox!
2023-01-30 14:27:06 +01:00

71 lines
1.7 KiB
Go

package sconf
import (
"bufio"
"fmt"
"io"
"os"
"reflect"
)
// ParseFile reads an sconf file from path into dst.
func ParseFile(path string, dst interface{}) error {
src, err := os.Open(path)
if err != nil {
return err
}
defer src.Close()
return parse(path, src, dst)
}
// Parse reads an sconf file from a reader into dst.
func Parse(src io.Reader, dst interface{}) error {
return parse("", src, dst)
}
// Describe writes an example sconf file describing v to w. The file includes all
// fields, values and documentation on the fields as configured with the "sconf"
// and "sconf-doc" struct tags. Describe does not detect recursive values and will
// attempt to write them.
func Describe(w io.Writer, v interface{}) error {
return describe(w, v, true, true)
}
// Write writes a valid sconf file describing v to w, without comments, without
// zero values of optional fields. Write does not detect recursive values and
// will attempt to write them.
func Write(w io.Writer, v interface{}) error {
return describe(w, v, false, false)
}
// WriteDocs is like Write, but does write comments.
func WriteDocs(w io.Writer, v interface{}) error {
return describe(w, v, false, true)
}
func describe(w io.Writer, v interface{}, keepZero bool, docs bool) (err error) {
value := reflect.ValueOf(v)
t := value.Type()
if t.Kind() == reflect.Ptr {
value = value.Elem()
t = value.Type()
}
if t.Kind() != reflect.Struct {
return fmt.Errorf("top level object must be a struct, is a %T", v)
}
defer func() {
x := recover()
if x == nil {
return
}
if e, ok := x.(writeError); ok {
err = error(e)
} else {
panic(x)
}
}()
wr := &writer{out: bufio.NewWriter(w), keepZero: keepZero, docs: docs}
wr.describeStruct(value)
wr.flush()
return nil
}