Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,7 @@ func (d *decodeState) array(v reflect.Value) {
if v.Kind() == reflect.Slice {
// Grow slice if necessary
if i >= v.Cap() {
newcap := v.Cap() + v.Cap()/2
if newcap < 4 {
newcap = 4
}
newcap := max(v.Cap()+v.Cap()/2, 4)
newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
reflect.Copy(newv, v)
v.Set(newv)
Expand Down Expand Up @@ -581,7 +578,7 @@ func (d *decodeState) array(v reflect.Value) {
}

var nullLiteral = []byte("null")
var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
var textUnmarshalerType = reflect.TypeFor[encoding.TextUnmarshaler]()

// object consumes an object from d.data[d.off-1:], decoding into the value v.
// the first byte ('{') of the object has been read already.
Expand Down Expand Up @@ -808,12 +805,12 @@ func (d *decodeState) convertNumber(s string) (any, error) {
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)}
return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeFor[float64](), Offset: int64(d.off)}
}
return f, nil
}

var numberType = reflect.TypeOf(Number(""))
var numberType = reflect.TypeFor[Number]()

// literalStore decodes a literal stored in item into v.
//
Expand Down
34 changes: 17 additions & 17 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ func (u unmarshalerText) MarshalText() ([]byte, error) {
}

func (u *unmarshalerText) UnmarshalText(b []byte) error {
pos := bytes.Index(b, []byte(":"))
if pos == -1 {
before, after, ok := bytes.Cut(b, []byte(":"))
if !ok {
return errors.New("missing separator")
}
u.A, u.B = string(b[:pos]), string(b[pos+1:])
u.A, u.B = string(before), string(after)
return nil
}

Expand All @@ -106,7 +106,7 @@ type ustructText struct {
type u8marshal uint8

func (u8 u8marshal) MarshalText() ([]byte, error) {
return []byte(fmt.Sprintf("u%d", u8)), nil
return fmt.Appendf(nil, "u%d", u8), nil
}

var errMissingU8Prefix = errors.New("missing 'u' prefix")
Expand Down Expand Up @@ -262,7 +262,7 @@ func mapAddr(x map[string]int) *map[string]int { return &x }
type byteWithMarshalJSON byte

func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil
return fmt.Appendf(nil, `"Z%.2x"`, byte(b)), nil
}

func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error {
Expand Down Expand Up @@ -290,7 +290,7 @@ func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
type byteWithMarshalText byte

func (b byteWithMarshalText) MarshalText() ([]byte, error) {
return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil
return fmt.Appendf(nil, `Z%.2x`, byte(b)), nil
}

func (b *byteWithMarshalText) UnmarshalText(data []byte) error {
Expand Down Expand Up @@ -318,7 +318,7 @@ func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error {
type intWithMarshalJSON int

func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil
return fmt.Appendf(nil, `"Z%.2x"`, int(b)), nil
}

func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error {
Expand Down Expand Up @@ -346,7 +346,7 @@ func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
type intWithMarshalText int

func (b intWithMarshalText) MarshalText() ([]byte, error) {
return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil
return fmt.Appendf(nil, `Z%.2x`, int(b)), nil
}

func (b *intWithMarshalText) UnmarshalText(data []byte) error {
Expand Down Expand Up @@ -400,7 +400,7 @@ var unmarshalTests = []unmarshalTest{
{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
{in: "null", ptr: new(any), out: nil},
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeFor[string](), 7, "T", "X"}},
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
Expand Down Expand Up @@ -515,22 +515,22 @@ var unmarshalTests = []unmarshalTest{
{
in: `{"abc":"abc"}`,
ptr: new(map[int]string),
err: &UnmarshalTypeError{Value: "number abc", Type: reflect.TypeOf(0), Offset: 2},
err: &UnmarshalTypeError{Value: "number abc", Type: reflect.TypeFor[int](), Offset: 2},
},
{
in: `{"256":"abc"}`,
ptr: new(map[uint8]string),
err: &UnmarshalTypeError{Value: "number 256", Type: reflect.TypeOf(uint8(0)), Offset: 2},
err: &UnmarshalTypeError{Value: "number 256", Type: reflect.TypeFor[uint8](), Offset: 2},
},
{
in: `{"128":"abc"}`,
ptr: new(map[int8]string),
err: &UnmarshalTypeError{Value: "number 128", Type: reflect.TypeOf(int8(0)), Offset: 2},
err: &UnmarshalTypeError{Value: "number 128", Type: reflect.TypeFor[int8](), Offset: 2},
},
{
in: `{"-1":"abc"}`,
ptr: new(map[uint8]string),
err: &UnmarshalTypeError{Value: "number -1", Type: reflect.TypeOf(uint8(0)), Offset: 2},
err: &UnmarshalTypeError{Value: "number -1", Type: reflect.TypeFor[uint8](), Offset: 2},
},

// Map keys can be encoding.TextUnmarshalers.
Expand Down Expand Up @@ -664,12 +664,12 @@ var unmarshalTests = []unmarshalTest{
{
in: `{"2009-11-10T23:00:00Z": "hello world"}`,
ptr: &map[Point]string{},
err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[Point]string{}), Offset: 1},
err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeFor[map[Point]string](), Offset: 1},
},
{
in: `{"asdf": "hello world"}`,
ptr: &map[unmarshaler]string{},
err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[unmarshaler]string{}), Offset: 1},
err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeFor[map[unmarshaler]string](), Offset: 1},
},

// related to issue 13783.
Expand Down Expand Up @@ -769,7 +769,7 @@ var unmarshalTests = []unmarshalTest{
Value: "string",
Struct: "V",
Field: "F2",
Type: reflect.TypeOf(int32(0)),
Type: reflect.TypeFor[int32](),
Offset: 20,
},
},
Expand All @@ -780,7 +780,7 @@ var unmarshalTests = []unmarshalTest{
Value: "string",
Struct: "V",
Field: "F2",
Type: reflect.TypeOf(int32(0)),
Type: reflect.TypeFor[int32](),
Offset: 30,
},
},
Expand Down
11 changes: 5 additions & 6 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"encoding"
"encoding/base64"
"fmt"
"maps"
"math"
"reflect"
"runtime"
Expand Down Expand Up @@ -376,9 +377,9 @@ func typeEncoder(t reflect.Type) encoderFunc {
}

var (
marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
orderedObjectType = reflect.TypeOf(new(OrderedObject)).Elem()
marshalerType = reflect.TypeFor[Marshaler]()
textMarshalerType = reflect.TypeFor[encoding.TextMarshaler]()
orderedObjectType = reflect.TypeFor[OrderedObject]()
)

// newTypeEncoder constructs an encoderFunc for a type.
Expand Down Expand Up @@ -1334,9 +1335,7 @@ func cachedTypeFields(t reflect.Type) []field {
fieldCache.mu.Lock()
m, _ = fieldCache.value.Load().(map[reflect.Type][]field)
newM := make(map[reflect.Type][]field, len(m)+1)
for k, v := range m {
newM[k] = v
}
maps.Copy(newM, m)
Comment thread
roman-khimov marked this conversation as resolved.
newM[t] = f
fieldCache.value.Store(newM)
fieldCache.mu.Unlock()
Expand Down
2 changes: 1 addition & 1 deletion encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Optionals struct {
Uo uint `json:"uo,omitempty"`

Str struct{} `json:"str"`
Sto struct{} `json:"sto,omitempty"`
Sto struct{} `json:"sto,omitempty"` //nolint:modernize
}

var optionalsExpected = `{
Expand Down
15 changes: 3 additions & 12 deletions scanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,7 @@ func BenchmarkSkipValue(b *testing.B) {
func diff(t *testing.T, a, b []byte) {
for i := 0; ; i++ {
if i >= len(a) || i >= len(b) || a[i] != b[i] {
j := i - 10
if j < 0 {
j = 0
}
j := max(i-10, 0)
t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:]))
return
}
Expand Down Expand Up @@ -306,10 +303,7 @@ func genString(stddev float64) string {
}

func genArray(n int) []any {
f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
if f > n {
f = n
}
f := min(int(math.Abs(rand.NormFloat64())*math.Min(10, float64(n/2))), n)
if f < 1 {
f = 1
}
Expand All @@ -321,10 +315,7 @@ func genArray(n int) []any {
}

func genMap(n int) map[string]any {
f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
if f > n {
f = n
}
f := min(int(math.Abs(rand.NormFloat64())*math.Min(10, float64(n/2))), n)
if n > 0 && f == 0 {
f = 1
}
Expand Down
4 changes: 2 additions & 2 deletions tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ type tagOptions string
// parseTag splits a struct field's json tag into its name and
// comma-separated options.
func parseTag(tag string) (string, tagOptions) {
if idx := strings.Index(tag, ","); idx != -1 {
return tag[:idx], tagOptions(tag[idx+1:])
if before, after, ok := strings.Cut(tag, ","); ok {
return before, tagOptions(after)
}
return tag, tagOptions("")
}
Expand Down
Loading