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)) }