Skip to content

Commit

Permalink
Merge pull request #10 from go-faster/feat/writer
Browse files Browse the repository at this point in the history
feat: add writer
  • Loading branch information
ernado authored Jan 12, 2022
2 parents 37d8206 + 2421721 commit 0a14eba
Show file tree
Hide file tree
Showing 28 changed files with 820 additions and 641 deletions.
4 changes: 2 additions & 2 deletions bool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func Test_false(t *testing.T) {
func Test_write_true_false(t *testing.T) {
should := require.New(t)
w := GetEncoder()
w.True()
w.False()
w.Bool(true)
w.Bool(false)
w.Bool(false)
should.Equal("truefalsefalse", string(w.Bytes()))
}
32 changes: 16 additions & 16 deletions dec_int.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ func init() {

func (d *Decoder) uint(size int) (uint, error) {
if size == 32 {
v, err := d.Uint32()
v, err := d.UInt32()
return uint(v), err
}
v, err := d.Uint64()
v, err := d.UInt64()
return uint(v), err
}

// Uint read uint.
func (d *Decoder) Uint() (uint, error) {
// UInt read uint.
func (d *Decoder) UInt() (uint, error) {
return d.uint(strconv.IntSize)
}

Expand All @@ -59,7 +59,7 @@ func (d *Decoder) Int32() (int32, error) {
return 0, errors.Wrap(err, "byte")
}
if c == '-' {
val, err := d.readUint32()
val, err := d.readUInt32()
if err != nil {
return 0, err
}
Expand All @@ -69,7 +69,7 @@ func (d *Decoder) Int32() (int32, error) {
return -int32(val), nil
}
d.unread()
val, err := d.readUint32()
val, err := d.readUInt32()
if err != nil {
return 0, err
}
Expand All @@ -79,12 +79,12 @@ func (d *Decoder) Int32() (int32, error) {
return int32(val), nil
}

// Uint32 read uint32
func (d *Decoder) Uint32() (uint32, error) {
return d.readUint32()
// UInt32 read uint32
func (d *Decoder) UInt32() (uint32, error) {
return d.readUInt32()
}

func (d *Decoder) readUint32() (uint32, error) {
func (d *Decoder) readUInt32() (uint32, error) {
c, err := d.byte()
if err != nil {
return 0, errors.Wrap(err, "byte")
Expand Down Expand Up @@ -187,7 +187,7 @@ func (d *Decoder) Int64() (int64, error) {
if err != nil {
return 0, err
}
val, err := d.readUint64(c)
val, err := d.readUInt64(c)
if err != nil {
return 0, err
}
Expand All @@ -196,7 +196,7 @@ func (d *Decoder) Int64() (int64, error) {
}
return -int64(val), nil
}
val, err := d.readUint64(c)
val, err := d.readUInt64(c)
if err != nil {
return 0, err
}
Expand All @@ -206,16 +206,16 @@ func (d *Decoder) Int64() (int64, error) {
return int64(val), nil
}

// Uint64 read uint64
func (d *Decoder) Uint64() (uint64, error) {
// UInt64 read uint64
func (d *Decoder) UInt64() (uint64, error) {
c, err := d.byte()
if err != nil {
return 0, errors.Wrap(err, "byte")
}
return d.readUint64(c)
return d.readUInt64(c)
}

func (d *Decoder) readUint64(c byte) (uint64, error) {
func (d *Decoder) readUInt64(c byte) (uint64, error) {
ind := intDigits[c]
if ind == 0 {
return 0, nil // single zero
Expand Down
2 changes: 1 addition & 1 deletion dec_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func BenchmarkDecoder_Uint(b *testing.B) {
d := GetDecoder()
for i := 0; i < b.N; i++ {
d.ResetBytes(data)
if _, err := d.Uint(); err != nil {
if _, err := d.UInt(); err != nil {
b.Fatal(err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion dec_skip_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Benchmark_skip(b *testing.B) {
if err := iter.ObjBytes(func(i *Decoder, key []byte) error {
switch string(key) {
case "code":
v, err := iter.Uint64()
v, err := iter.UInt64()
result.Code = v
return err
default:
Expand Down
84 changes: 24 additions & 60 deletions enc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "io"
//
// Zero value is valid.
type Encoder struct {
buf []byte // underlying buffer
w Writer // underlying writer
indent int // count of spaces for single indentation level

// first handles state for comma and indentation writing.
Expand All @@ -27,14 +27,12 @@ type Encoder struct {

// Write implements io.Writer.
func (e *Encoder) Write(p []byte) (n int, err error) {
e.buf = append(e.buf, p...)
return len(p), nil
return e.w.Write(p)
}

// WriteTo implements io.WriterTo.
func (e *Encoder) WriteTo(w io.Writer) (n int64, err error) {
wrote, err := w.Write(e.buf)
return int64(wrote), err
return e.w.WriteTo(w)
}

// SetIdent sets length of single indentation step.
Expand All @@ -49,86 +47,51 @@ func (e Encoder) String() string {

// Reset resets underlying buffer.
func (e *Encoder) Reset() {
e.buf = e.buf[:0]
e.w.Buf = e.w.Buf[:0]
e.first = e.first[:0]
}

// Bytes returns underlying buffer.
func (e Encoder) Bytes() []byte { return e.buf }
func (e Encoder) Bytes() []byte { return e.w.Buf }

// SetBytes sets underlying buffer.
func (e *Encoder) SetBytes(buf []byte) { e.buf = buf }
func (e *Encoder) SetBytes(buf []byte) { e.w.Buf = buf }

// byte writes a single byte.
func (e *Encoder) byte(c byte) {
e.buf = append(e.buf, c)
}

func (e *Encoder) twoBytes(c1, c2 byte) {
e.buf = append(e.buf, c1, c2)
}

func (e *Encoder) threeBytes(c1, c2, c3 byte) {
e.buf = append(e.buf, c1, c2, c3)
}

func (e *Encoder) fourBytes(c1, c2, c3, c4 byte) {
e.buf = append(e.buf, c1, c2, c3, c4)
}

func (e *Encoder) fiveBytes(c1, c2, c3, c4, c5 byte) {
e.buf = append(e.buf, c1, c2, c3, c4, c5)
e.w.Buf = append(e.w.Buf, c)
}

// RawStr writes string as raw json.
func (e *Encoder) RawStr(v string) {
e.comma()
e.rawStr(v)
}

func (e *Encoder) rawStr(v string) {
e.buf = append(e.buf, v...)
e.w.RawStr(v)
}

// Raw writes byte slice as raw json.
func (e *Encoder) Raw(b []byte) {
e.comma()
e.buf = append(e.buf, b...)
e.w.Raw(b)
}

// Null writes null.
func (e *Encoder) Null() {
e.comma()
e.fourBytes('n', 'u', 'l', 'l')
}

// True writes true.
func (e *Encoder) True() {
e.comma()
e.fourBytes('t', 'r', 'u', 'e')
}

// False writes false.
func (e *Encoder) False() {
e.comma()
e.fiveBytes('f', 'a', 'l', 's', 'e')
e.w.Null()
}

// Bool encodes boolean.
func (e *Encoder) Bool(v bool) {
if v {
e.True()
} else {
e.False()
}
e.comma()
e.w.Bool(v)
}

// ObjStart writes object start, performing indentation if needed.
//
// Use Obj as convenience helper for writing objects.
func (e *Encoder) ObjStart() {
e.comma()
e.byte('{')
e.w.ObjStart()
e.begin()
e.writeIndent()
}
Expand All @@ -139,11 +102,10 @@ func (e *Encoder) ObjStart() {
//
// Use Field as convenience helper for encoding fields.
func (e *Encoder) FieldStart(field string) {
e.Str(field)
e.comma()
e.w.FieldStart(field)
if e.indent > 0 {
e.twoBytes(':', ' ')
} else {
e.byte(':')
e.byte(' ')
}
if len(e.first) > 0 {
e.first[e.current()] = true
Expand All @@ -164,13 +126,14 @@ func (e *Encoder) Field(name string, f func(e *Encoder)) {
func (e *Encoder) ObjEnd() {
e.end()
e.writeIndent()
e.byte('}')
e.w.ObjEnd()
}

// ObjEmpty writes empty object.
func (e *Encoder) ObjEmpty() {
e.comma()
e.twoBytes('{', '}')
e.w.ObjStart()
e.w.ObjEnd()
}

// Obj writes start of object, invokes callback and writes end of object.
Expand All @@ -191,15 +154,16 @@ func (e *Encoder) Obj(f func(e *Encoder)) {
// Use Arr as convenience helper for writing arrays.
func (e *Encoder) ArrStart() {
e.comma()
e.byte('[')
e.w.ArrStart()
e.begin()
e.writeIndent()
}

// ArrEmpty writes empty array.
func (e *Encoder) ArrEmpty() {
e.comma()
e.twoBytes('[', ']')
e.w.ArrStart()
e.w.ArrEnd()
}

// ArrEnd writes end of array, performing indentation if needed.
Expand All @@ -208,7 +172,7 @@ func (e *Encoder) ArrEmpty() {
func (e *Encoder) ArrEnd() {
e.end()
e.writeIndent()
e.byte(']')
e.w.ArrEnd()
}

// Arr writes start of array, invokes callback and writes end of array.
Expand All @@ -230,6 +194,6 @@ func (e *Encoder) writeIndent() {
}
e.byte('\n')
for i := 0; i < len(e.first)*e.indent; i++ {
e.buf = append(e.buf, ' ')
e.w.Buf = append(e.w.Buf, ' ')
}
}
13 changes: 1 addition & 12 deletions enc_b64.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
package jx

import "encoding/base64"

// Base64 encodes data as standard base64 encoded string.
//
// Same as encoding/json, base64.StdEncoding or RFC 4648.
func (e *Encoder) Base64(data []byte) {
if data == nil {
e.Null()
return
}
e.comma()
e.byte('"')
encodedLen := base64.StdEncoding.EncodedLen(len(data))
start := len(e.buf)
e.buf = append(e.buf, make([]byte, encodedLen)...)
base64.StdEncoding.Encode(e.buf[start:], data)
e.byte('"')
e.w.Base64(data)
}
2 changes: 1 addition & 1 deletion enc_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func encodeObject(w *Encoder) {
w.ObjStart()

w.FieldStart("objectId")
w.Uint64(8838243212)
w.UInt64(8838243212)

w.FieldStart("name")
w.Str("Jane Doe")
Expand Down
4 changes: 2 additions & 2 deletions enc_comma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ func TestEncoder_comma(t *testing.T) {
e.Float32(3.0)
e.Float64(4.5)
e.Num(Num{'2', '3'})
e.True()
e.False()
e.Bool(true)
e.Bool(false)
e.Null()
e.Base64(Raw{1})
e.Bool(true)
Expand Down
10 changes: 8 additions & 2 deletions enc_float.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ package jx
// Float32 encodes float32.
//
// NB: Infinities and NaN are represented as null.
func (e *Encoder) Float32(v float32) { e.float(float64(v), 32) }
func (e *Encoder) Float32(v float32) {
e.comma()
e.w.Float32(v)
}

// Float64 encodes float64.
//
// NB: Infinities and NaN are represented as null.
func (e *Encoder) Float64(v float64) { e.float(v, 64) }
func (e *Encoder) Float64(v float64) {
e.comma()
e.w.Float64(v)
}
Loading

0 comments on commit 0a14eba

Please sign in to comment.