Skip to content

Commit 2f02d56

Browse files
authored
Use int64 for object or array length (#27)
WARNING: This commit includes breaking changes. When processing JSON as a stream, it is conceivable that the total number of elements in a JSON object or array exceeds a 32-bit integer. Switch from int to int64 for a similar reason as why io.Copy returns int64 instead of int. Note that the depth still uses an int because the stack must be representable in memory, which is limited to the native integer width of the platform. This is similar to how io.Reader.Read returns an int because the length of a []byte cannot possibly be larger than the largest int.
1 parent a256f16 commit 2f02d56

File tree

5 files changed

+16
-10
lines changed

5 files changed

+16
-10
lines changed

arshal_test.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -3666,7 +3666,10 @@ func TestMarshal(t *testing.T) {
36663666
want: `[null,{},null,{},null,null,{},{},null,{},null,null,{},"LAST"]`,
36673667
opts: []Options{
36683668
WithMarshalers(func() *Marshalers {
3669-
type P [2]int
3669+
type P struct {
3670+
D int
3671+
N int64
3672+
}
36703673
type PV struct {
36713674
P P
36723675
V any
@@ -7714,7 +7717,10 @@ func TestUnmarshal(t *testing.T) {
77147717
}),
77157718
opts: []Options{
77167719
WithUnmarshalers(func() *Unmarshalers {
7717-
type P [2]int
7720+
type P struct {
7721+
D int
7722+
N int64
7723+
}
77187724
type PV struct {
77197725
P P
77207726
V any

jsontext/decode.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ func (d *Decoder) StackDepth() int {
10371037
// Each name and value in a JSON object is counted separately,
10381038
// so the effective number of members would be half the length.
10391039
// A complete JSON object must have an even length.
1040-
func (d *Decoder) StackIndex(i int) (Kind, int) {
1040+
func (d *Decoder) StackIndex(i int) (Kind, int64) {
10411041
// NOTE: Keep in sync with Encoder.StackIndex.
10421042
switch s := d.s.Tokens.index(i); {
10431043
case i > 0 && s.isObject():

jsontext/encode.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ func (e *Encoder) StackDepth() int {
902902
// Each name and value in a JSON object is counted separately,
903903
// so the effective number of members would be half the length.
904904
// A complete JSON object must have an even length.
905-
func (e *Encoder) StackIndex(i int) (Kind, int) {
905+
func (e *Encoder) StackIndex(i int) (Kind, int64) {
906906
// NOTE: Keep in sync with Decoder.StackIndex.
907907
switch s := e.s.Tokens.index(i); {
908908
case i > 0 && s.isObject():

jsontext/state.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func (m *stateMachine) index(i int) *stateEntry {
133133

134134
// DepthLength reports the current nested depth and
135135
// the length of the last JSON object or array.
136-
func (m stateMachine) DepthLength() (int, int) {
136+
func (m stateMachine) DepthLength() (int, int64) {
137137
return m.Depth(), m.Last.Length()
138138
}
139139

@@ -342,8 +342,8 @@ const (
342342

343343
// Length reports the number of elements in the JSON object or array.
344344
// Each name and value in an object entry is treated as a separate element.
345-
func (e stateEntry) Length() int {
346-
return int(e & stateCountMask)
345+
func (e stateEntry) Length() int64 {
346+
return int64(e & stateCountMask)
347347
}
348348

349349
// isObject reports whether this is a JSON object.

jsontext/state_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestStateMachine(t *testing.T) {
2020
type operation any
2121
type (
2222
// stackLengths checks the results of stateEntry.length accessors.
23-
stackLengths []int
23+
stackLengths []int64
2424

2525
// appendTokens is sequence of token kinds to append where
2626
// none of them are expected to fail.
@@ -156,12 +156,12 @@ func TestStateMachine(t *testing.T) {
156156
for _, op := range ops {
157157
switch op := op.(type) {
158158
case stackLengths:
159-
var got []int
159+
var got []int64
160160
for i := 0; i < state.Depth(); i++ {
161161
e := state.index(i)
162162
got = append(got, e.Length())
163163
}
164-
want := []int(op)
164+
want := []int64(op)
165165
if !reflect.DeepEqual(got, want) {
166166
t.Fatalf("%s: stack lengths mismatch:\ngot %v\nwant %v", sequence, got, want)
167167
}

0 commit comments

Comments
 (0)