Skip to content

Commit

Permalink
refactor: another iteration of api simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
ernado committed Oct 30, 2021
1 parent d51d775 commit 7c05406
Show file tree
Hide file tree
Showing 26 changed files with 224 additions and 325 deletions.
31 changes: 13 additions & 18 deletions any_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package jx

import (
"bytes"
hexEnc "encoding/hex"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -132,7 +131,7 @@ func (v *Any) Read(d *Decoder) error {
v.Type = AnyBool
case Object:
v.Type = AnyObj
if err := d.Object(func(r *Decoder, s string) error {
if err := d.Obj(func(r *Decoder, s string) error {
var elem Any
if err := elem.Read(r); err != nil {
return xerrors.Errorf("elem: %w", err)
Expand All @@ -147,7 +146,7 @@ func (v *Any) Read(d *Decoder) error {
return nil
case Array:
v.Type = AnyArr
if err := d.Array(func(r *Decoder) error {
if err := d.Arr(func(r *Decoder) error {
var elem Any
if err := elem.Read(r); err != nil {
return xerrors.Errorf("elem: %w", err)
Expand All @@ -171,7 +170,7 @@ func (v Any) Write(w *Encoder) error {
}
switch v.Type {
case AnyStr:
w.String(v.Str)
w.Str(v.Str)
case AnyFloat:
if err := w.Float64(v.Float); err != nil {
return err
Expand Down Expand Up @@ -256,18 +255,16 @@ func (v Any) String() string {
}

func TestAny_Read(t *testing.T) {
t.Run("Object", func(t *testing.T) {
t.Run("Obj", func(t *testing.T) {
var v Any
const input = `{"foo":{"bar":1,"baz":[1,2,3.14],"200":null}}`
r := DecodeString(input)
r := DecodeStr(input)
assert.NoError(t, v.Read(r))
assert.Equal(t, `{foo: {bar: 1, baz: [1, 2, f3.14], 200: null}}`, v.String())

buf := new(bytes.Buffer)
w := NewEncoder(buf, 1024)
require.NoError(t, w.Any(v))
require.NoError(t, w.Flush())
require.Equal(t, input, buf.String(), "encoded value should equal to input")
e := NewEncoder()
require.NoError(t, e.Any(v))
require.Equal(t, input, e.String(), "encoded value should equal to input")
})
t.Run("Inputs", func(t *testing.T) {
for _, tt := range []struct {
Expand All @@ -282,19 +279,17 @@ func TestAny_Read(t *testing.T) {
r := DecodeBytes(input)
require.NoError(t, v.Read(r))

buf := new(bytes.Buffer)
s := NewEncoder(buf, 1024)
require.NoError(t, v.Write(s))
require.NoError(t, s.Flush())
require.Equal(t, tt.Input, buf.String(), "encoded value should equal to input")
e := NewEncoder()
require.NoError(t, v.Write(e))
require.Equal(t, tt.Input, e.String(), "encoded value should equal to input")

var otherValue Any
r.ResetBytes(buf.Bytes())
r.ResetBytes(e.Bytes())

if err := otherValue.Read(r); err != nil {
t.Error(err)
t.Log(hexEnc.Dump(input))
t.Log(hexEnc.Dump(buf.Bytes()))
t.Log(hexEnc.Dump(e.Bytes()))
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func Benchmark_large_file(b *testing.B) {

for n := 0; n < b.N; n++ {
iter.ResetBytes(data)
if err := iter.Array(func(iter *Decoder) error {
if err := iter.Arr(func(iter *Decoder) error {
return iter.Skip()
}); err != nil {
b.Fatal(err)
Expand Down
11 changes: 4 additions & 7 deletions bool_test.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
package jx

import (
"bytes"
"testing"

"github.com/stretchr/testify/require"
)

func Test_true(t *testing.T) {
should := require.New(t)
iter := DecodeString(`true`)
iter := DecodeStr(`true`)
should.True(iter.Bool())
}

func Test_false(t *testing.T) {
should := require.New(t)
iter := DecodeString(`false`)
iter := DecodeStr(`false`)
should.False(iter.Bool())
}

func Test_write_true_false(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
w := NewEncoder(buf, 4096)
w := NewEncoder()
w.True()
w.False()
w.Bool(false)
should.NoError(w.Flush())
should.Equal("truefalsefalse", buf.String())
should.Equal("truefalsefalse", string(w.Bytes()))
}
8 changes: 4 additions & 4 deletions dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ func DecodeBytes(input []byte) *Decoder {
}
}

// DecodeString creates a Decoder that reads string as json.
func DecodeString(input string) *Decoder {
// DecodeStr creates a Decoder that reads string as json.
func DecodeStr(input string) *Decoder {
return DecodeBytes([]byte(input))
}

Expand Down Expand Up @@ -222,15 +222,15 @@ func (d *Decoder) unread() { d.head-- }
// limit maximum depth of nesting, as allowed by https://tools.ietf.org/html/rfc7159#section-9
const maxDepth = 10000

func (d *Decoder) incrementDepth() error {
func (d *Decoder) incDepth() error {
d.depth++
if d.depth > maxDepth {
return xerrors.New("max depth")
}
return nil
}

func (d *Decoder) decrementDepth() error {
func (d *Decoder) decDepth() error {
d.depth--
if d.depth < 0 {
return xerrors.New("negative depth")
Expand Down
10 changes: 5 additions & 5 deletions dec_arr.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ func (d *Decoder) Elem() (ok bool, err error) {
}
}

// Array reads array and calls f on each array element.
func (d *Decoder) Array(f func(d *Decoder) error) error {
// Arr reads array and calls f on each array element.
func (d *Decoder) Arr(f func(d *Decoder) error) error {
if err := d.expectNext('['); err != nil {
return xerrors.Errorf("start: %w", err)
}
if err := d.incrementDepth(); err != nil {
if err := d.incDepth(); err != nil {
return xerrors.Errorf("inc: %w", err)
}
c, err := d.next()
Expand All @@ -49,7 +49,7 @@ func (d *Decoder) Array(f func(d *Decoder) error) error {
return err
}
if c == ']' {
return d.decrementDepth()
return d.decDepth()
}
d.unread()
if err := f(d); err != nil {
Expand All @@ -74,5 +74,5 @@ func (d *Decoder) Array(f func(d *Decoder) error) error {
if c != ']' {
return xerrors.Errorf("end: %w", badToken(c))
}
return d.decrementDepth()
return d.decDepth()
}
12 changes: 6 additions & 6 deletions dec_capture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func TestIterator_Capture(t *testing.T) {
}`
i := GetDecoder()
i.ResetBytes([]byte(input))
err := i.Object(func(i *Decoder, key string) error {
return i.Array(func(i *Decoder) error {
err := i.Obj(func(i *Decoder, key string) error {
return i.Arr(func(i *Decoder) error {
// Reading "type" field value first.
var typ string
if err := i.Capture(func(i *Decoder) error {
return i.Object(func(i *Decoder, key string) error {
return i.Obj(func(i *Decoder, key string) error {
switch key {
case "type":
s, err := i.String()
Expand All @@ -44,7 +44,7 @@ func TestIterator_Capture(t *testing.T) {
return err
}
// Reading objects depending on type.
return i.Object(func(i *Decoder, key string) error {
return i.Obj(func(i *Decoder, key string) error {
if key == "type" {
s, err := i.String()
if err != nil {
Expand Down Expand Up @@ -83,10 +83,10 @@ func BenchmarkIterator_Skip(b *testing.B) {
}

func TestDecoder_Capture(t *testing.T) {
i := DecodeString(`["foo", "bar", "baz"]`)
i := DecodeStr(`["foo", "bar", "baz"]`)
var elems int
if err := i.Capture(func(i *Decoder) error {
return i.Array(func(i *Decoder) error {
return i.Arr(func(i *Decoder) error {
elems++
return i.Skip()
})
Expand Down
18 changes: 9 additions & 9 deletions dec_obj.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ import (
"golang.org/x/xerrors"
)

// ObjectBytes calls f for every key in object, using byte slice as key.
// 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) ObjectBytes(f func(d *Decoder, key []byte) error) error {
func (d *Decoder) ObjBytes(f func(d *Decoder, key []byte) error) error {
if err := d.expectNext('{'); err != nil {
return xerrors.Errorf("start: %w", err)
}
if err := d.incrementDepth(); err != nil {
if err := d.incDepth(); err != nil {
return xerrors.Errorf("inc: %w", err)
}
c, err := d.next()
if err != nil {
return xerrors.Errorf("next: %w", err)
}
if c == '}' {
return d.decrementDepth()
return d.decDepth()
}
d.unread()

Expand Down Expand Up @@ -61,14 +61,14 @@ func (d *Decoder) ObjectBytes(f func(d *Decoder, key []byte) error) error {
if c != '}' {
return xerrors.Errorf("end: %w", badToken(c))
}
return d.decrementDepth()
return d.decDepth()
}

// Object reads json object, calling f on each field.
// Obj reads json object, calling f on each field.
//
// Use ObjectBytes to reduce heap allocations for keys.
func (d *Decoder) Object(f func(d *Decoder, key string) error) error {
return d.ObjectBytes(func(d *Decoder, key []byte) error {
// Use ObjBytes to reduce heap allocations for keys.
func (d *Decoder) Obj(f func(d *Decoder, key string) error) error {
return d.ObjBytes(func(d *Decoder, key []byte) error {
return f(d, string(key))
})
}
4 changes: 2 additions & 2 deletions dec_obj_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
)

func TestDecoder_ObjectBytes(t *testing.T) {
i := DecodeString(`{"id":1,"randomNumber":10}`)
i := DecodeStr(`{"id":1,"randomNumber":10}`)
met := map[string]struct{}{}
require.NoError(t, i.ObjectBytes(func(i *Decoder, key []byte) error {
require.NoError(t, i.ObjBytes(func(i *Decoder, key []byte) error {
switch string(key) {
case "id":
v, err := i.Int64()
Expand Down
4 changes: 2 additions & 2 deletions dec_skip.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,14 @@ func (d *Decoder) strFastSkip() (ok bool, err error) {

func (d *Decoder) skipObject() error {
d.unread()
return d.ObjectBytes(func(iter *Decoder, _ []byte) error {
return d.ObjBytes(func(iter *Decoder, _ []byte) error {
return iter.Skip()
})
}

func (d *Decoder) skipArray() error {
d.unread()
return d.Array(func(iter *Decoder) error {
return d.Arr(func(iter *Decoder) error {
return iter.Skip()
})
}
2 changes: 1 addition & 1 deletion dec_skip_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func Benchmark_skip(b *testing.B) {
for n := 0; n < b.N; n++ {
result := TestResp{}
iter := DecodeBytes(input)
if err := iter.ObjectBytes(func(i *Decoder, key []byte) error {
if err := iter.ObjBytes(func(i *Decoder, key []byte) error {
switch string(key) {
case "code":
v, err := iter.Uint64()
Expand Down
2 changes: 1 addition & 1 deletion dec_skip_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func Test_skip(t *testing.T) {
should := require.New(t)
ptrVal := reflect.New(valType)
stdErr := json.Unmarshal([]byte(input), ptrVal.Interface())
iter := DecodeString(input)
iter := DecodeStr(input)
if stdErr == nil {
should.NoError(iter.Skip())
should.ErrorIs(iter.Null(), io.ErrUnexpectedEOF)
Expand Down
Loading

0 comments on commit 7c05406

Please sign in to comment.