asciigoat's INI parser
https://asciigoat.org/ini
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
1.5 KiB
83 lines
1.5 KiB
package ini |
|
|
|
import ( |
|
"bytes" |
|
"io" |
|
"strings" |
|
|
|
"asciigoat.org/core" |
|
"asciigoat.org/core/reflective" |
|
"asciigoat.org/ini/parser" |
|
) |
|
|
|
const ( |
|
decPrefixLiteral = "ini: Decode" |
|
) |
|
|
|
var ( |
|
decINIPrefix = decPrefixLiteral[0:3] |
|
decDecPrefix = decPrefixLiteral[5:] |
|
) |
|
|
|
// Decoder ... |
|
type Decoder struct { |
|
io.Closer |
|
|
|
out *reflective.Reflection |
|
p *parser.Parser |
|
queue []*token |
|
} |
|
|
|
// Decode ... |
|
func (dec *Decoder) Decode(v any) error { |
|
defer dec.Close() |
|
|
|
r, err := reflective.New(v) |
|
switch e := err.(type) { |
|
case *reflective.InvalidUnmarshalError: |
|
// customize error |
|
e.Prefix = decINIPrefix |
|
e.Method = decDecPrefix |
|
case *reflective.UnmarshalTypeError: |
|
// customize error |
|
e.Prefix = decPrefixLiteral |
|
case nil: |
|
// good reflection. Go! |
|
dec.out = r |
|
err = dec.p.Run() |
|
} |
|
|
|
return err |
|
} |
|
|
|
// NewDecoder creates a Decoder using the provided [io.Reader] |
|
// as source |
|
func NewDecoder(r io.Reader) *Decoder { |
|
rc := core.NewReadCloser(r) |
|
switch { |
|
case rc == nil: |
|
return nil |
|
default: |
|
dec := &Decoder{ |
|
p: parser.NewParser(rc), |
|
Closer: rc, |
|
} |
|
|
|
// callbacks |
|
dec.p.OnToken = dec.parserOnToken |
|
dec.p.OnError = dec.parserOnError |
|
|
|
return dec |
|
} |
|
} |
|
|
|
// NewDecoderBytes creates a Decoder using the provided bytes array |
|
// as source |
|
func NewDecoderBytes(b []byte) *Decoder { |
|
return NewDecoder(bytes.NewReader(b)) |
|
} |
|
|
|
// NewDecoderString creates a Decoder over a provided string of data |
|
func NewDecoderString(s string) *Decoder { |
|
return NewDecoder(strings.NewReader(s)) |
|
}
|
|
|