summaryrefslogtreecommitdiff
path: root/decode.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-01-29 20:59:37 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-01-30 22:56:40 -0700
commitb3f4186f2b8e992f56f898784b1cd28bfd7550ca (patch)
tree9c9f0086c386a63a12b622945248916d51c480a5 /decode.go
parentbc1bacc410ddfa444c5bf0e56f33a7da440658ae (diff)
Invent "barriers" instead of nesting parsers
Diffstat (limited to 'decode.go')
-rw-r--r--decode.go56
1 files changed, 33 insertions, 23 deletions
diff --git a/decode.go b/decode.go
index 8fab267..60b530f 100644
--- a/decode.go
+++ b/decode.go
@@ -104,7 +104,7 @@ const maxNestingDepth = 10000
// an io.Reader.
func NewDecoder(r io.RuneScanner) *Decoder {
return &Decoder{
- io: &runeTypeScannerImpl{
+ io: runeTypeScanner{
inner: r,
parser: internal.Parser{
MaxDepth: maxNestingDepth,
@@ -245,6 +245,7 @@ func (dec *Decoder) Decode(ptr any) (err error) {
}
dec.io.Reset()
+ dec.io.PushReadBarrier()
defer func() {
if r := recover(); r != nil {
if de, ok := r.(decodeError); ok {
@@ -257,6 +258,7 @@ func (dec *Decoder) Decode(ptr any) (err error) {
}
}()
dec.decode(ptrVal.Elem(), false)
+ dec.io.PopReadBarrier()
return nil
}
@@ -319,12 +321,21 @@ func (dec *Decoder) expectRuneType(ec rune, et internal.RuneType, gt reflect.Typ
}
}
-type decRuneTypeScanner struct {
+type decRuneScanner struct {
dec *Decoder
+ eof bool
}
-func (sc *decRuneTypeScanner) ReadRuneType() (rune, int, internal.RuneType, error) {
+func (sc *decRuneScanner) ReadRune() (rune, int, error) {
+ if sc.eof {
+ return 0, 0, io.EOF
+ }
c, s, t, e := sc.dec.io.ReadRuneType()
+ if t == internal.RuneTypeEOF {
+ sc.eof = true
+ sc.dec.io.PopReadBarrier()
+ return 0, 0, io.EOF
+ }
if e != nil {
panic(decodeError{
Field: sc.dec.structStackStr(),
@@ -333,28 +344,17 @@ func (sc *decRuneTypeScanner) ReadRuneType() (rune, int, internal.RuneType, erro
Err: e,
})
}
- return c, s, t, nil
+ return c, s, nil
}
-func (sc *decRuneTypeScanner) ReadRune() (rune, int, error) {
- r, s, t, _ := sc.ReadRuneType()
- switch t {
- case internal.RuneTypeEOF:
- return 0, 0, io.EOF
- default:
- return r, s, nil
- }
+func (sc *decRuneScanner) UnreadRune() error {
+ return sc.dec.io.UnreadRune()
}
-func (sc *decRuneTypeScanner) UnreadRune() error { return sc.dec.io.UnreadRune() }
-func (sc *decRuneTypeScanner) InputOffset() int64 { return sc.dec.InputOffset() }
-func (sc *decRuneTypeScanner) Reset() { sc.dec.io.Reset() }
-
-func (dec *Decoder) limitingScanner() runeTypeScanner {
- return &elemRuneTypeScanner{
- inner: &decRuneTypeScanner{
- dec: dec,
- },
+func (dec *Decoder) limitingScanner() io.RuneScanner {
+ dec.io.PushReadBarrier()
+ return &decRuneScanner{
+ dec: dec,
}
}
@@ -867,7 +867,12 @@ func DecodeObject(r io.RuneScanner, decodeKey, decodeVal func(io.RuneScanner) er
}
}
}()
- dec := NewDecoder(r)
+ var dec *Decoder
+ if dr, ok := r.(*decRuneScanner); ok {
+ dec = dr.dec
+ } else {
+ dec = NewDecoder(r)
+ }
dec.posStackPush()
defer dec.posStackPop()
dec.decodeObject(nil,
@@ -947,7 +952,12 @@ func DecodeArray(r io.RuneScanner, decodeMember func(r io.RuneScanner) error) (e
}
}
}()
- dec := NewDecoder(r)
+ var dec *Decoder
+ if dr, ok := r.(*decRuneScanner); ok {
+ dec = dr.dec
+ } else {
+ dec = NewDecoder(r)
+ }
dec.posStackPush()
defer dec.posStackPop()
dec.decodeArray(nil, func() {