package ini import ( "bytes" "io" "strings" "asciigoat.org/core" "asciigoat.org/core/reflection" "asciigoat.org/ini/parser" ) // Decoder ... type Decoder[T any] struct { io.Closer out *reflection.Reflection[T] p *parser.Parser queue []*token } // Decode ... func (dec *Decoder[T]) Decode(v *T) error { defer dec.Close() r, err := reflection.New(v) switch e := err.(type) { case *reflection.InvalidUnmarshalError: // customize error e.Prefix = "ini" e.Method = "Decode" return e case nil: // good reflection. Go! dec.out = r return dec.p.Run() default: // other errors panic("unreachable") } } // NewDecoder creates a Decoder using the provided [io.Reader] // as source func NewDecoder[T any](r io.Reader) *Decoder[T] { rc := core.NewReadCloser(r) switch { case rc == nil: return nil default: dec := &Decoder[T]{ p: parser.NewParser(rc), Closer: rc, } dec.init() return dec } } func (dec *Decoder[T]) init() { dec.p.OnToken = dec.parserOnToken dec.p.OnError = dec.parserOnError } // NewDecoderBytes creates a Decoder using the provided bytes array // as source func NewDecoderBytes[T any](b []byte) *Decoder[T] { return NewDecoder[T](bytes.NewReader(b)) } // NewDecoderString creates a Decoder over a provided string of data func NewDecoderString[T any](s string) *Decoder[T] { return NewDecoder[T](strings.NewReader(s)) }