summaryrefslogtreecommitdiff
path: root/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'decode.go')
-rw-r--r--decode.go32
1 files changed, 21 insertions, 11 deletions
diff --git a/decode.go b/decode.go
index f911ac3..f351037 100644
--- a/decode.go
+++ b/decode.go
@@ -30,22 +30,29 @@ import (
// JSON representation of themselves. Decodable is a
// low-memory-overhead replacement for the json.Unmarshaler interface.
//
-// The io.RuneScanner passed to DecodeJSON...
+// On the io.RuneScanner passed to DecodeJSON:
//
-// - ...will return ErrInvalidUnreadRune .UnreadRune if the last
+// - .UnreadRune() will return ErrInvalidUnreadRune if the last
// operation was not a successful .ReadRune() call.
//
-// - ...will return EOF at the end of the JSON value; it is not
-// possible for DecodeJSON to read past the end of the value in to
-// another value.
+// - .ReadRune() will return io.EOF at the end of the JSON value; it
+// is not possible for .ReadRune() to read past the end of the
+// value in to another value.
//
-// - ...if invalid JSON is encountered, will return the invalid rune
-// with err!=nil. Implementations are encouraged to simply
-// `return err` if .ReadRune returns an error.
+// - .ReadRune() will never return invalid JSON; if invalid JSON is
+// encountered, it will use a panic-based mechanism to transfer
+// control back to the Decoder.
+//
+// - .ReadRune() never return an error other than io.EOF; if an I/O
+// error is encountered, it will use a panic-based mechanism to
+// transfer control back to the Decoder.
//
// DecodeJSON is expected to consume the entire scanner until io.EOF
// or another is encountered; if it does not, then the parent Decode
// call will return a *DecodeTypeError.
+//
+// Implementor's note: "limitingScanner" is the thing to search for in
+// decode.go if you want to read up on that io.RuneScanner.
type Decodable interface {
DecodeJSON(io.RuneScanner) error
}
@@ -146,9 +153,11 @@ func (dec *Decoder) More() bool {
func (dec *Decoder) stackPush(par reflect.Type, idx any) {
dec.stack = append(dec.stack, decodeStackItem{par, idx})
}
+
func (dec *Decoder) stackPop() {
dec.stack = dec.stack[:len(dec.stack)-1]
}
+
func (dec *Decoder) stackStr() string {
var buf strings.Builder
buf.WriteString("v")
@@ -319,6 +328,7 @@ func (sc *decRuneTypeScanner) ReadRuneType() (rune, int, internal.RuneType, erro
}
return c, s, t, nil
}
+
func (sc *decRuneTypeScanner) ReadRune() (rune, int, error) {
r, s, t, _ := sc.ReadRuneType()
switch t {
@@ -659,13 +669,13 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
case internal.RuneTypeStringBeg:
if typ.Elem() == byteType {
var buf bytes.Buffer
- dec.decodeString(typ, newBase64Decoder(&buf))
+ dec.decodeString(typ, internal.NewBase64Decoder(&buf))
val.Set(reflect.ValueOf(buf.Bytes()))
} else {
// TODO: Surely there's a better way. At the very least, we should
// avoid buffering.
var buf bytes.Buffer
- dec.decodeString(typ, newBase64Decoder(&buf))
+ dec.decodeString(typ, internal.NewBase64Decoder(&buf))
bs := buf.Bytes()
val.Set(reflect.MakeSlice(typ, len(bs), len(bs)))
for i := 0; i < len(bs); i++ {
@@ -850,7 +860,7 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er
dec.panicType(t.JSONType(), nil, fmt.Errorf("did not consume entire %s", t.JSONType()))
}
})
- return
+ return err
}
func (dec *Decoder) decodeObject(gTyp reflect.Type, decodeKey, decodeVal func()) {