Skip to content

Commit

Permalink
feat: smarter object skip
Browse files Browse the repository at this point in the history
  • Loading branch information
tdakkota committed Jan 14, 2022
1 parent 8242f8a commit 16fcaf1
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 25 deletions.
15 changes: 5 additions & 10 deletions dec_obj.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,16 @@ import (
"github.com/go-faster/errors"
)

func skipObjBytes(d *Decoder, _ []byte) error { return d.Skip() }

// ObjBytes calls f for every key in object, using byte slice as key.
//
// The key value is valid only until f is not returned.
func (d *Decoder) ObjBytes(f func(d *Decoder, key []byte) error) error {
skip := f == nil
if skip {
// No callback is provided, skipping object.
// Drop keys, skip values.
f = skipObjBytes
}
if err := d.consume('{'); err != nil {
return errors.Wrap(err, "start")
}
if f == nil {
return d.skipObj()
}
if err := d.incDepth(); err != nil {
return errors.Wrap(err, "inc")
}
Expand All @@ -31,7 +26,7 @@ func (d *Decoder) ObjBytes(f func(d *Decoder, key []byte) error) error {
}
d.unread()

k, err := d.str(value{ignore: skip, raw: true})
k, err := d.str(value{raw: true})
if err != nil {
return errors.Wrap(err, "str")
}
Expand All @@ -52,7 +47,7 @@ func (d *Decoder) ObjBytes(f func(d *Decoder, key []byte) error) error {
return errors.Wrap(err, "next")
}
for c == ',' {
k, err := d.str(value{ignore: skip, raw: true})
k, err := d.str(value{raw: true})
if err != nil {
return errors.Wrap(err, "str")
}
Expand Down
51 changes: 49 additions & 2 deletions dec_skip.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ var (
}
)

// skipStr reads one JSON string.
//
// Assumes first quote was consumed.
func (d *Decoder) skipStr() error {
readStr:
for {
Expand Down Expand Up @@ -356,9 +359,53 @@ readEscaped:
goto readStr
}

// skipObj reads JSON object.
//
// Assumes first bracket was consumed.
func (d *Decoder) skipObj() error {
d.unread()
return d.Obj(nil)
if err := d.incDepth(); err != nil {
return errors.Wrap(err, "inc")
}

c, err := d.more()
if err != nil {
return errors.Wrap(err, "next")
}
switch c {
case '}':
return d.decDepth()
case '"':
d.unread()
default:
return badToken(c)
}

for {
if err := d.consume('"'); err != nil {
return err
}
if err := d.skipStr(); err != nil {
return errors.Wrap(err, "read field name")
}
if err := d.consume(':'); err != nil {
return errors.Wrap(err, "field")
}
if err := d.Skip(); err != nil {
return err
}
c, err := d.more()
if err != nil {
return errors.Wrap(err, "read comma")
}
switch c {
case ',':
continue
case '}':
return d.decDepth()
default:
return badToken(c)
}
}
}

func (d *Decoder) skipArr() error {
Expand Down
8 changes: 8 additions & 0 deletions dec_skip_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,15 @@ func TestDecoder_Skip(t *testing.T) {
"nul", // invalid
"nil", // invalid
"null", // valid
`{`, // invalid
`{}`, // valid
`{"1}`, // invalid
`{"1:}`, // invalid
`{"1,}`, // invalid
`{"1":}`, // invalid
`{"\1":}`, // invalid
`{"1",}`, // invalid
`{"1":,}`, // invalid
`{"hello":"world"}`, // valid
`{hello:"world"}`, // invalid
`{"hello:"world"}`, // invalid
Expand Down
15 changes: 2 additions & 13 deletions dec_str.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,18 @@ func (d *Decoder) StrAppend(b []byte) ([]byte, error) {
}

type value struct {
buf []byte
raw bool // false forces buf reuse
ignore bool
buf []byte
raw bool // false forces buf reuse
}

func (v value) rune(r rune) value {
if v.ignore {
return v
}
return value{
buf: appendRune(v.buf, r),
raw: v.raw,
}
}

func (v value) byte(b byte) value {
if v.ignore {
return v
}
return value{
buf: append(v.buf, b),
raw: v.raw,
Expand Down Expand Up @@ -72,10 +65,6 @@ func (d *Decoder) str(v value) (value, error) {
}
if c == '"' {
// End of string in fast path.
if v.ignore {
d.head += i + 1
return value{}, nil
}
str := buf[:i]
d.head += i + 1
if v.raw {
Expand Down

0 comments on commit 16fcaf1

Please sign in to comment.