diff --git a/decoder.go b/decoder.go new file mode 100644 index 0000000..b8c2611 --- /dev/null +++ b/decoder.go @@ -0,0 +1,74 @@ +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 +} + +// 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)) +} diff --git a/decoder_error.go b/decoder_error.go new file mode 100644 index 0000000..19d58c9 --- /dev/null +++ b/decoder_error.go @@ -0,0 +1,18 @@ +package ini + +import ( + "log" + + "asciigoat.org/core/lexer" +) + +func (*Decoder[T]) parserOnError(pos lexer.Position, content string, err error) error { + log.Printf("%s: %s %s: %q: %v", "ini", pos, "error:", content, err) + + return &lexer.Error{ + Line: pos.Line, + Column: pos.Column, + Content: content, + Err: err, + } +} diff --git a/decoder_token.go b/decoder_token.go new file mode 100644 index 0000000..4b5dc98 --- /dev/null +++ b/decoder_token.go @@ -0,0 +1,14 @@ +package ini + +import ( + "log" + + "asciigoat.org/core/lexer" + "asciigoat.org/ini/parser" +) + +func (*Decoder[T]) parserOnToken(pos lexer.Position, typ parser.TokenType, value string) error { + log.Printf("%s: %s %s %q", "ini", pos, typ, value) + + return nil +}