gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit f801fd9a9b630c005451ac293c7ca64fa1123be4
parent acc87b92070551fbd05b1ef178851952e8cf2681
Author: francoispqt <francois@parquet.ninja>
Date:   Sat, 23 Jun 2018 01:45:14 +0800

add encoding number types

Diffstat:
Mencode_array.go | 19+++++++++++++++++++
Mencode_number_int.go | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aencode_number_int_test.go | 538+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mencode_number_test.go | 7++++---
Mencode_number_uint.go | 134++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Aencode_number_uint_test.go | 533+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mgojay/gen_struct_unmarshal_tpl.go | 4++--
7 files changed, 1361 insertions(+), 6 deletions(-)

diff --git a/encode_array.go b/encode_array.go @@ -128,3 +128,22 @@ func (enc *Encoder) ArrayKeyOmitEmpty(key string, v MarshalerJSONArray) { v.MarshalJSONArray(enc) enc.writeByte(']') } + +// EncodeArrayFunc is a custom func type implementing MarshaleArray. +// Use it to cast a func(*Encoder) to Marshal an object. +// +// enc := gojay.NewEncoder(io.Writer) +// enc.EncodeArray(gojay.EncodeArrayFunc(func(enc *gojay.Encoder) { +// enc.AddStringKey("hello", "world") +// })) +type EncodeArrayFunc func(*Encoder) + +// MarshalJSONArray implements MarshalerJSONArray. +func (f EncodeArrayFunc) MarshalJSONArray(enc *Encoder) { + f(enc) +} + +// IsNil implements MarshalerJSONArray. +func (f EncodeArrayFunc) IsNil() bool { + return f == nil +} diff --git a/encode_number_int.go b/encode_number_int.go @@ -191,3 +191,135 @@ func (enc *Encoder) Int64KeyOmitEmpty(key string, v int64) { enc.writeBytes(objKey) enc.buf = strconv.AppendInt(enc.buf, v, 10) } + +// AddInt32 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) AddInt32(v int32) { + enc.Int64(int64(v)) +} + +// AddInt32OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) AddInt32OmitEmpty(v int32) { + enc.Int64OmitEmpty(int64(v)) +} + +// Int32 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) Int32(v int32) { + enc.Int64(int64(v)) +} + +// Int32OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) Int32OmitEmpty(v int32) { + enc.Int64OmitEmpty(int64(v)) +} + +// AddInt32Key adds an int32 to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) AddInt32Key(key string, v int32) { + enc.Int64Key(key, int64(v)) +} + +// AddInt32KeyOmitEmpty adds an int32 to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) AddInt32KeyOmitEmpty(key string, v int32) { + enc.Int64KeyOmitEmpty(key, int64(v)) +} + +// Int32Key adds an int32 to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) Int32Key(key string, v int32) { + enc.Int64Key(key, int64(v)) +} + +// Int32KeyOmitEmpty adds an int32 to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) Int32KeyOmitEmpty(key string, v int32) { + enc.Int64KeyOmitEmpty(key, int64(v)) +} + +// AddInt16 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) AddInt16(v int16) { + enc.Int64(int64(v)) +} + +// AddInt16OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) AddInt16OmitEmpty(v int16) { + enc.Int64OmitEmpty(int64(v)) +} + +// Int16 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) Int16(v int16) { + enc.Int64(int64(v)) +} + +// Int16OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) Int16OmitEmpty(v int16) { + enc.Int64OmitEmpty(int64(v)) +} + +// AddInt16Key adds an int16 to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) AddInt16Key(key string, v int16) { + enc.Int64Key(key, int64(v)) +} + +// AddInt16KeyOmitEmpty adds an int16 to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) AddInt16KeyOmitEmpty(key string, v int16) { + enc.Int64KeyOmitEmpty(key, int64(v)) +} + +// Int16Key adds an int16 to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) Int16Key(key string, v int16) { + enc.Int64Key(key, int64(v)) +} + +// Int16KeyOmitEmpty adds an int16 to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) Int16KeyOmitEmpty(key string, v int16) { + enc.Int64KeyOmitEmpty(key, int64(v)) +} + +// AddInt8 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) AddInt8(v int8) { + enc.Int64(int64(v)) +} + +// AddInt8OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) AddInt8OmitEmpty(v int8) { + enc.Int64OmitEmpty(int64(v)) +} + +// Int8 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) Int8(v int8) { + enc.Int64(int64(v)) +} + +// Int8OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) Int8OmitEmpty(v int8) { + enc.Int64OmitEmpty(int64(v)) +} + +// AddInt8Key adds an int8 to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) AddInt8Key(key string, v int8) { + enc.Int64Key(key, int64(v)) +} + +// AddInt8KeyOmitEmpty adds an int8 to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) AddInt8KeyOmitEmpty(key string, v int8) { + enc.Int64KeyOmitEmpty(key, int64(v)) +} + +// Int8Key adds an int8 to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) Int8Key(key string, v int8) { + enc.Int64Key(key, int64(v)) +} + +// Int8KeyOmitEmpty adds an int8 to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) Int8KeyOmitEmpty(key string, v int8) { + enc.Int64KeyOmitEmpty(key, int64(v)) +} diff --git a/encode_number_int_test.go b/encode_number_int_test.go @@ -0,0 +1,538 @@ +package gojay + +import ( + "math" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEncoderInt64(t *testing.T) { + var testCasesBasic = []struct { + name string + v int64 + expectedJSON string + }{ + { + name: "basic", + v: int64(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt64, + expectedJSON: "[9223372036854775807,9223372036854775807]", + }, + { + name: "big", + v: int64(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int64(testCase.v) + enc.AddInt64(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + + var testCasesOmitEmpty = []struct { + name string + v int64 + expectedJSON string + }{ + { + name: "basic", + v: int64(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt64, + expectedJSON: "[9223372036854775807,9223372036854775807]", + }, + { + name: "big", + v: int64(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int64OmitEmpty(testCase.v) + enc.AddInt64OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v int64 + expectedJSON string + }{ + { + name: "basic", + v: int64(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt64, + expectedJSON: `{"foo":9223372036854775807,"bar":9223372036854775807}`, + }, + { + name: "big", + v: int64(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int64Key("foo", testCase.v) + enc.AddInt64Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + + var testCasesKeyOmitEmpty = []struct { + name string + v int64 + expectedJSON string + }{ + { + name: "basic", + v: int64(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt64, + expectedJSON: `{"foo":9223372036854775807,"bar":9223372036854775807}`, + }, + { + name: "big", + v: int64(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int64KeyOmitEmpty("foo", testCase.v) + enc.AddInt64KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} + +func TestEncoderInt32(t *testing.T) { + var testCasesBasic = []struct { + name string + v int32 + expectedJSON string + }{ + { + name: "basic", + v: int32(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt32, + expectedJSON: "[2147483647,2147483647]", + }, + { + name: "big", + v: int32(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int32(testCase.v) + enc.AddInt32(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v int32 + expectedJSON string + }{ + { + name: "basic", + v: int32(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt32, + expectedJSON: "[2147483647,2147483647]", + }, + { + name: "big", + v: int32(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int32OmitEmpty(testCase.v) + enc.AddInt32OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v int32 + expectedJSON string + }{ + { + name: "basic", + v: int32(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt32, + expectedJSON: `{"foo":2147483647,"bar":2147483647}`, + }, + { + name: "big", + v: int32(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int32Key("foo", testCase.v) + enc.AddInt32Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + + var testCasesKeyOmitEmpty = []struct { + name string + v int32 + expectedJSON string + }{ + { + name: "basic", + v: int32(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt32, + expectedJSON: `{"foo":2147483647,"bar":2147483647}`, + }, + { + name: "big", + v: int32(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int32KeyOmitEmpty("foo", testCase.v) + enc.AddInt32KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} + +func TestEncoderInt16(t *testing.T) { + var testCasesBasic = []struct { + name string + v int16 + expectedJSON string + }{ + { + name: "basic", + v: int16(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt16, + expectedJSON: "[32767,32767]", + }, + { + name: "big", + v: int16(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int16(testCase.v) + enc.AddInt16(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v int16 + expectedJSON string + }{ + { + name: "basic", + v: int16(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt16, + expectedJSON: "[32767,32767]", + }, + { + name: "big", + v: int16(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int16OmitEmpty(testCase.v) + enc.AddInt16OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v int16 + expectedJSON string + }{ + { + name: "basic", + v: int16(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt16, + expectedJSON: `{"foo":32767,"bar":32767}`, + }, + { + name: "big", + v: int16(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int16Key("foo", testCase.v) + enc.AddInt16Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + + var testCasesKeyOmitEmpty = []struct { + name string + v int16 + expectedJSON string + }{ + { + name: "basic", + v: int16(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt16, + expectedJSON: `{"foo":32767,"bar":32767}`, + }, + { + name: "big", + v: int16(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int16KeyOmitEmpty("foo", testCase.v) + enc.AddInt16KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} + +func TestEncoderInt8(t *testing.T) { + var testCasesBasic = []struct { + name string + v int8 + expectedJSON string + }{ + { + name: "basic", + v: int8(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt8, + expectedJSON: "[127,127]", + }, + { + name: "big", + v: int8(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int8(testCase.v) + enc.AddInt8(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v int8 + expectedJSON string + }{ + { + name: "basic", + v: int8(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxInt8, + expectedJSON: "[127,127]", + }, + { + name: "big", + v: int8(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Int8OmitEmpty(testCase.v) + enc.AddInt8OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v int8 + expectedJSON string + }{ + { + name: "basic", + v: int8(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt8, + expectedJSON: `{"foo":127,"bar":127}`, + }, + { + name: "big", + v: int8(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int8Key("foo", testCase.v) + enc.AddInt8Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + + var testCasesKeyOmitEmpty = []struct { + name string + v int8 + expectedJSON string + }{ + { + name: "basic", + v: int8(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxInt8, + expectedJSON: `{"foo":127,"bar":127}`, + }, + { + name: "big", + v: int8(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Int8KeyOmitEmpty("foo", testCase.v) + enc.AddInt8KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} diff --git a/encode_number_test.go b/encode_number_test.go @@ -4,9 +4,10 @@ import ( "strings" "testing" - "github.com/stretchr/testify/assert" - "math" "fmt" + "math" + + "github.com/stretchr/testify/assert" ) func TestEncoderNumberEncodeAPI(t *testing.T) { @@ -356,7 +357,7 @@ func TestAddNumberFunc(t *testing.T) { }) } -func TestEncoderUint64(t *testing.T) { +func TestEncodeUint64(t *testing.T) { builder := &strings.Builder{} enc := BorrowEncoder(builder) err := enc.Encode(uint64(145509)) diff --git a/encode_number_uint.go b/encode_number_uint.go @@ -2,7 +2,7 @@ package gojay import "strconv" -// EncodeUint64 encodes an int64 to JSON +// EncodeUint32 encodes an int64 to JSON func (enc *Encoder) EncodeUint64(n uint64) error { if enc.isPooled == 1 { panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder")) @@ -96,3 +96,135 @@ func (enc *Encoder) Uint64KeyOmitEmpty(key string, v uint64) { enc.writeBytes(objKey) enc.buf = strconv.AppendUint(enc.buf, v, 10) } + +// AddUint32 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) AddUint32(v uint32) { + enc.Uint64(uint64(v)) +} + +// AddUint32OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) AddUint32OmitEmpty(v uint32) { + enc.Uint64OmitEmpty(uint64(v)) +} + +// Uint32 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) Uint32(v uint32) { + enc.Uint64(uint64(v)) +} + +// Uint32OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) Uint32OmitEmpty(v uint32) { + enc.Uint64OmitEmpty(uint64(v)) +} + +// AddUint32Key adds an int to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) AddUint32Key(key string, v uint32) { + enc.Uint64Key(key, uint64(v)) +} + +// AddUint32KeyOmitEmpty adds an int to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) AddUint32KeyOmitEmpty(key string, v uint32) { + enc.Uint64KeyOmitEmpty(key, uint64(v)) +} + +// Uint32Key adds an int to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) Uint32Key(key string, v uint32) { + enc.Uint64Key(key, uint64(v)) +} + +// Uint32KeyOmitEmpty adds an int to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) Uint32KeyOmitEmpty(key string, v uint32) { + enc.Uint64KeyOmitEmpty(key, uint64(v)) +} + +// AddUint16 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) AddUint16(v uint16) { + enc.Uint64(uint64(v)) +} + +// AddUint16OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) AddUint16OmitEmpty(v uint16) { + enc.Uint64OmitEmpty(uint64(v)) +} + +// Uint16 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) Uint16(v uint16) { + enc.Uint64(uint64(v)) +} + +// Uint16OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) Uint16OmitEmpty(v uint16) { + enc.Uint64OmitEmpty(uint64(v)) +} + +// AddUint16Key adds an int to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) AddUint16Key(key string, v uint16) { + enc.Uint64Key(key, uint64(v)) +} + +// AddUint16KeyOmitEmpty adds an int to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) AddUint16KeyOmitEmpty(key string, v uint16) { + enc.Uint64KeyOmitEmpty(key, uint64(v)) +} + +// Uint16Key adds an int to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) Uint16Key(key string, v uint16) { + enc.Uint64Key(key, uint64(v)) +} + +// Uint16KeyOmitEmpty adds an int to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) Uint16KeyOmitEmpty(key string, v uint16) { + enc.Uint64KeyOmitEmpty(key, uint64(v)) +} + +// AddUint8 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) AddUint8(v uint8) { + enc.Uint64(uint64(v)) +} + +// AddUint8OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) AddUint8OmitEmpty(v uint8) { + enc.Uint64OmitEmpty(uint64(v)) +} + +// Uint8 adds an int to be encoded, must be used inside a slice or array encoding (does not encode a key) +func (enc *Encoder) Uint8(v uint8) { + enc.Uint64(uint64(v)) +} + +// Uint8OmitEmpty adds an int to be encoded and skips it if its value is 0, +// must be used inside a slice or array encoding (does not encode a key). +func (enc *Encoder) Uint8OmitEmpty(v uint8) { + enc.Uint64OmitEmpty(uint64(v)) +} + +// AddUint8Key adds an int to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) AddUint8Key(key string, v uint8) { + enc.Uint64Key(key, uint64(v)) +} + +// AddUint8KeyOmitEmpty adds an int to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) AddUint8KeyOmitEmpty(key string, v uint8) { + enc.Uint64KeyOmitEmpty(key, uint64(v)) +} + +// Uint8Key adds an int to be encoded, must be used inside an object as it will encode a key +func (enc *Encoder) Uint8Key(key string, v uint8) { + enc.Uint64Key(key, uint64(v)) +} + +// Uint8KeyOmitEmpty adds an int to be encoded and skips it if its value is 0. +// Must be used inside an object as it will encode a key. +func (enc *Encoder) Uint8KeyOmitEmpty(key string, v uint8) { + enc.Uint64KeyOmitEmpty(key, uint64(v)) +} diff --git a/encode_number_uint_test.go b/encode_number_uint_test.go @@ -0,0 +1,533 @@ +package gojay + +import ( + "math" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEncoderUint64(t *testing.T) { + var testCasesBasic = []struct { + name string + v uint64 + expectedJSON string + }{ + { + name: "basic", + v: uint64(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint64, + expectedJSON: "[18446744073709551615,18446744073709551615]", + }, + { + name: "big", + v: uint64(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint64(testCase.v) + enc.AddUint64(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v uint64 + expectedJSON string + }{ + { + name: "basic", + v: uint64(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint64, + expectedJSON: "[18446744073709551615,18446744073709551615]", + }, + { + name: "big", + v: uint64(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint64OmitEmpty(testCase.v) + enc.AddUint64OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v uint64 + expectedJSON string + }{ + { + name: "basic", + v: uint64(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint64, + expectedJSON: `{"foo":18446744073709551615,"bar":18446744073709551615}`, + }, + { + name: "big", + v: uint64(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint64Key("foo", testCase.v) + enc.AddUint64Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyOmitEmpty = []struct { + name string + v uint64 + expectedJSON string + }{ + { + name: "basic", + v: uint64(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint64, + expectedJSON: `{"foo":18446744073709551615,"bar":18446744073709551615}`, + }, + { + name: "big", + v: uint64(0), + expectedJSON: "{}", + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint64KeyOmitEmpty("foo", testCase.v) + enc.AddUint64KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} + +func TestEncoderUint32(t *testing.T) { + var testCasesBasic = []struct { + name string + v uint32 + expectedJSON string + }{ + { + name: "basic", + v: uint32(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint32, + expectedJSON: "[4294967295,4294967295]", + }, + { + name: "big", + v: uint32(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint32(testCase.v) + enc.AddUint32(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v uint32 + expectedJSON string + }{ + { + name: "basic", + v: uint32(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint32, + expectedJSON: "[4294967295,4294967295]", + }, + { + name: "big", + v: uint32(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint32OmitEmpty(testCase.v) + enc.AddUint32OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v uint32 + expectedJSON string + }{ + { + name: "basic", + v: uint32(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint32, + expectedJSON: `{"foo":4294967295,"bar":4294967295}`, + }, + { + name: "big", + v: uint32(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint32Key("foo", testCase.v) + enc.AddUint32Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyOmitEmpty = []struct { + name string + v uint32 + expectedJSON string + }{ + { + name: "basic", + v: uint32(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint32, + expectedJSON: `{"foo":4294967295,"bar":4294967295}`, + }, + { + name: "big", + v: uint32(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint32KeyOmitEmpty("foo", testCase.v) + enc.AddUint32KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} + +func TestEncoderUint16(t *testing.T) { + var testCasesBasic = []struct { + name string + v uint16 + expectedJSON string + }{ + { + name: "basic", + v: uint16(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint16, + expectedJSON: "[65535,65535]", + }, + { + name: "big", + v: uint16(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint16(testCase.v) + enc.AddUint16(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v uint16 + expectedJSON string + }{ + { + name: "basic", + v: uint16(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint16, + expectedJSON: "[65535,65535]", + }, + { + name: "big", + v: uint16(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint16OmitEmpty(testCase.v) + enc.AddUint16OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v uint16 + expectedJSON string + }{ + { + name: "basic", + v: uint16(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint16, + expectedJSON: `{"foo":65535,"bar":65535}`, + }, + { + name: "big", + v: uint16(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint16Key("foo", testCase.v) + enc.AddUint16Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyOmitEmpty = []struct { + name string + v uint16 + expectedJSON string + }{ + { + name: "basic", + v: uint16(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint16, + expectedJSON: `{"foo":65535,"bar":65535}`, + }, + { + name: "big", + v: uint16(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint16KeyOmitEmpty("foo", testCase.v) + enc.AddUint16KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} + +func TestEncoderUint8(t *testing.T) { + var testCasesBasic = []struct { + name string + v uint8 + expectedJSON string + }{ + { + name: "basic", + v: uint8(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint8, + expectedJSON: "[255,255]", + }, + { + name: "big", + v: uint8(0), + expectedJSON: "[0,0]", + }, + } + for _, testCase := range testCasesBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint8(testCase.v) + enc.AddUint8(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesOmitEmpty = []struct { + name string + v uint8 + expectedJSON string + }{ + { + name: "basic", + v: uint8(1), + expectedJSON: "[1,1]", + }, + { + name: "big", + v: math.MaxUint8, + expectedJSON: "[255,255]", + }, + { + name: "big", + v: uint8(0), + expectedJSON: "[]", + }, + } + for _, testCase := range testCasesOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeArrayFunc(func(enc *Encoder) { + enc.Uint8OmitEmpty(testCase.v) + enc.AddUint8OmitEmpty(testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyBasic = []struct { + name string + v uint8 + expectedJSON string + }{ + { + name: "basic", + v: uint8(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint8, + expectedJSON: `{"foo":255,"bar":255}`, + }, + { + name: "big", + v: uint8(0), + expectedJSON: `{"foo":0,"bar":0}`, + }, + } + for _, testCase := range testCasesKeyBasic { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint8Key("foo", testCase.v) + enc.AddUint8Key("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } + var testCasesKeyOmitEmpty = []struct { + name string + v uint8 + expectedJSON string + }{ + { + name: "basic", + v: uint8(1), + expectedJSON: `{"foo":1,"bar":1}`, + }, + { + name: "big", + v: math.MaxUint8, + expectedJSON: `{"foo":255,"bar":255}`, + }, + { + name: "big", + v: uint8(0), + expectedJSON: `{}`, + }, + } + for _, testCase := range testCasesKeyOmitEmpty { + t.Run(testCase.name, func(t *testing.T) { + var b = &strings.Builder{} + var enc = NewEncoder(b) + enc.Encode(EncodeObjectFunc(func(enc *Encoder) { + enc.Uint8KeyOmitEmpty("foo", testCase.v) + enc.AddUint8KeyOmitEmpty("bar", testCase.v) + })) + assert.Equal(t, testCase.expectedJSON, b.String()) + }) + } +} diff --git a/gojay/gen_struct_unmarshal_tpl.go b/gojay/gen_struct_unmarshal_tpl.go @@ -46,9 +46,9 @@ func (v *{{.StructName}}) NKeys() int { return {{.NKeys}} } "arr": &genTpl{ strTpl: ` if v.{{.Field}} == nil { arr := make({{.TypeName}}, 0) - v.{{.Field}} = &arr + v.{{.Field}} = arr } - return dec.Array(v.{{.Field}}) + return dec.Array(&v.{{.Field}}) `, }, }