Skip to content

Commit 554dba4

Browse files
committed
add encoder support Int64ToString and Uint64ToString (revert code style)
1 parent 918f5c6 commit 554dba4

File tree

10 files changed

+222
-27
lines changed

10 files changed

+222
-27
lines changed

api.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ type Config struct {
9494

9595
// Encode Infinity or Nan float into `null`, instead of returning an error.
9696
EncodeNullForInfOrNan bool
97+
98+
// Int64 or Uint64 into strings on Marshal
99+
Integer64BitToString bool
97100
}
98101

99102
var (

encode_test.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,4 +1224,110 @@ func TestMarshalInfOrNan(t *testing.T) {
12241224
assert.NotNil(t, err)
12251225
assert.True(t, strings.Contains(err.Error(), "json: unsupported value: NaN or ±Infinite"))
12261226
}
1227+
}
1228+
1229+
func TestInt64OrUInteger64BitToString(t *testing.T) {
1230+
int64ptr := int64(432556670863027541)
1231+
uint64ptr := uint64(12372850276778298372)
1232+
cases := []struct {
1233+
name string
1234+
val any
1235+
exceptTrue string
1236+
exceptFalse string
1237+
}{
1238+
{
1239+
name: "normal_map",
1240+
val: map[string]any{
1241+
"int": int(12),
1242+
"int64": int64(34),
1243+
"uint64": uint64(56),
1244+
},
1245+
exceptTrue: `{"int":12,"int64":"34","uint64":"56"}`,
1246+
exceptFalse: `{"int":12,"int64":34,"uint64":56}`,
1247+
},
1248+
{
1249+
name: "int_key_map",
1250+
val: map[int64]any{
1251+
int64(12): int(12),
1252+
int64(34): int64(34),
1253+
int64(56): uint64(56),
1254+
},
1255+
exceptTrue: `{"12":12,"34":"34","56":"56"}`,
1256+
exceptFalse: `{"12":12,"34":34,"56":56}`,
1257+
},
1258+
{
1259+
name: "normal_struct",
1260+
val: struct {
1261+
Int int `json:"int"`
1262+
Int64 int64 `json:"int64"`
1263+
Uint64 uint64 `json:"uint64"`
1264+
}{
1265+
Int: int(12),
1266+
Int64: int64(34),
1267+
Uint64: uint64(56),
1268+
},
1269+
exceptTrue: `{"int":12,"int64":"34","uint64":"56"}`,
1270+
exceptFalse: `{"int":12,"int64":34,"uint64":56}`,
1271+
},
1272+
{
1273+
name: "normal_slice",
1274+
val: []any{
1275+
int(12), int64(34), uint64(56),
1276+
},
1277+
exceptTrue: `[12,"34","56"]`,
1278+
exceptFalse: `[12,34,56]`,
1279+
},
1280+
{
1281+
name: "single_int64",
1282+
val: int64(34),
1283+
exceptTrue: `"34"`,
1284+
exceptFalse: `34`,
1285+
},
1286+
{
1287+
name: "single_uint64",
1288+
val: uint64(56),
1289+
exceptTrue: `"56"`,
1290+
exceptFalse: `56`,
1291+
},
1292+
{
1293+
name: "int64ptr",
1294+
val: struct {
1295+
Map map[string]any
1296+
}{map[string]any{"val": struct {
1297+
Int64Ptr any
1298+
Uint64Ptr any
1299+
Int64 any
1300+
Uint64 any
1301+
}{
1302+
Int64Ptr: &int64ptr,
1303+
Uint64Ptr: &uint64ptr,
1304+
Int64: int64(123),
1305+
Uint64: uint64(456),
1306+
}}},
1307+
exceptTrue: `{"Map":{"val":{"Int64Ptr":"432556670863027541",` +
1308+
`"Uint64Ptr":"12372850276778298372","Int64":"123","Uint64":"456"}}}`,
1309+
exceptFalse: `{"Map":{"val":{"Int64Ptr":432556670863027541,` +
1310+
`"Uint64Ptr":12372850276778298372,"Int64":123,"Uint64":456}}}`,
1311+
},
1312+
}
1313+
1314+
check := func(t *testing.T, except string, testRes []byte) {
1315+
var tmp1 any
1316+
assert.Nil(t, Unmarshal([]byte(testRes), &tmp1))
1317+
var tmp2 any
1318+
assert.Nil(t, Unmarshal([]byte(except), &tmp2))
1319+
assert.Equal(t, tmp2, tmp1)
1320+
}
1321+
1322+
for _, c := range cases {
1323+
t.Run(c.name, func(t *testing.T) {
1324+
b, e := Config{Integer64BitToString: true}.Froze().Marshal(c.val)
1325+
assert.Nil(t, e)
1326+
check(t, c.exceptTrue, b)
1327+
1328+
b, e = Config{Integer64BitToString: false}.Froze().Marshal(c.val)
1329+
assert.Nil(t, e)
1330+
check(t, c.exceptFalse, b)
1331+
})
1332+
}
12271333
}

encoder/encoder_native.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ const (
7373

7474
// Encode Infinity or Nan float into `null`, instead of returning an error.
7575
EncodeNullForInfOrNan Options = encoder.EncodeNullForInfOrNan
76+
77+
// Int64 or Uint64 into strings on Marshal
78+
Integer64BitToString Options = encoder.Integer64BitToString
7679
)
7780

7881

internal/encoder/alg/opts.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ const (
2525
BitValidateString
2626
BitNoValidateJSONMarshaler
2727
BitNoEncoderNewline
28-
BitEncodeNullForInfOrNan
28+
BitEncodeNullForInfOrNan
29+
BitInteger64BitToString
2930

3031
BitPointerValue = 63
3132
)

internal/encoder/compiler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func (self *Compiler) compileOps(p *ir.Program, sp int, vt reflect.Type) {
179179
case reflect.Bool:
180180
p.Add(ir.OP_bool)
181181
case reflect.Int:
182-
p.Add(ir.OP_int())
182+
p.Add(ir.OP_int(), ir.OP_i)
183183
case reflect.Int8:
184184
p.Add(ir.OP_i8)
185185
case reflect.Int16:
@@ -189,7 +189,7 @@ func (self *Compiler) compileOps(p *ir.Program, sp int, vt reflect.Type) {
189189
case reflect.Int64:
190190
p.Add(ir.OP_i64)
191191
case reflect.Uint:
192-
p.Add(ir.OP_uint())
192+
p.Add(ir.OP_uint(), ir.OP_ui)
193193
case reflect.Uint8:
194194
p.Add(ir.OP_u8)
195195
case reflect.Uint16:
@@ -301,7 +301,7 @@ func (self *Compiler) compileMapBodyTextKey(p *ir.Program, vk reflect.Type) {
301301
case reflect.Bool:
302302
p.Key(ir.OP_bool)
303303
case reflect.Int:
304-
p.Key(ir.OP_int())
304+
p.Key(ir.OP_int(), ir.OP_i)
305305
case reflect.Int8:
306306
p.Key(ir.OP_i8)
307307
case reflect.Int16:
@@ -311,7 +311,7 @@ func (self *Compiler) compileMapBodyTextKey(p *ir.Program, vk reflect.Type) {
311311
case reflect.Int64:
312312
p.Key(ir.OP_i64)
313313
case reflect.Uint:
314-
p.Key(ir.OP_uint())
314+
p.Key(ir.OP_uint(), ir.OP_ui)
315315
case reflect.Uint8:
316316
p.Key(ir.OP_u8)
317317
case reflect.Uint16:

internal/encoder/encoder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ const (
7373

7474
// Encode Infinity or Nan float into `null`, instead of returning an error.
7575
EncodeNullForInfOrNan Options = 1 << alg.BitEncodeNullForInfOrNan
76+
77+
// Int64 or Uint64 into strings on Marshal
78+
Integer64BitToString Options = 1 << alg.BitInteger64BitToString
7679
)
7780

7881
// Encoder represents a specific set of encoder configurations.

internal/encoder/ir/op.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ const (
3838
OP_i16
3939
OP_i32
4040
OP_i64
41+
OP_i
4142
OP_u8
4243
OP_u16
4344
OP_u32
4445
OP_u64
46+
OP_ui
4547
OP_f32
4648
OP_f64
4749
OP_str
@@ -99,10 +101,12 @@ var OpNames = [256]string{
99101
OP_i16: "i16",
100102
OP_i32: "i32",
101103
OP_i64: "i64",
104+
OP_i: "i",
102105
OP_u8: "u8",
103106
OP_u16: "u16",
104107
OP_u32: "u32",
105108
OP_u64: "u64",
109+
OP_ui: "ui",
106110
OP_f32: "f32",
107111
OP_f64: "f64",
108112
OP_str: "str",
@@ -197,12 +201,26 @@ func OP_is_zero_ints() Op {
197201

198202
type Instr struct {
199203
o Op
204+
co Op
205+
mapKey bool
200206
u int // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
201207
p unsafe.Pointer // maybe GoString.Ptr, or *GoType
202208
}
203209

204-
func NewInsOp(op Op) Instr {
205-
return Instr{o: op}
210+
func NewInsOp(op Op, compatOp ...Op) Instr {
211+
i := Instr{o: op, co: op}
212+
if len(compatOp) == 1 {
213+
i.co = compatOp[0]
214+
}
215+
return i
216+
}
217+
218+
func NewInsKeyOp(op Op, compatOp ...Op) Instr {
219+
i := Instr{o: op, co: op, mapKey: true}
220+
if len(compatOp) == 1 {
221+
i.co = compatOp[0]
222+
}
223+
return i
206224
}
207225

208226
func NewInsVi(op Op, vi int) Instr {
@@ -255,6 +273,14 @@ func (self Instr) Op() Op {
255273
return Op(self.o)
256274
}
257275

276+
func (self Instr) CompatOp() Op {
277+
return Op(self.co)
278+
}
279+
280+
func (self Instr) IsMapKey() bool {
281+
return self.mapKey
282+
}
283+
258284
func (self Instr) Vi() int {
259285
return self.u
260286
}
@@ -410,14 +436,14 @@ func (self Program) Rel(v []int) {
410436
}
411437
}
412438

413-
func (self *Program) Add(op Op) {
414-
*self = append(*self, NewInsOp(op))
439+
func (self *Program) Add(op Op, co ...Op) {
440+
*self = append(*self, NewInsOp(op, co...))
415441
}
416442

417-
func (self *Program) Key(op Op) {
443+
func (self *Program) Key(op Op, co ...Op) {
418444
*self = append(*self,
419445
NewInsVi(OP_byte, '"'),
420-
NewInsOp(op),
446+
NewInsKeyOp(op, co...),
421447
NewInsVi(OP_byte, '"'),
422448
)
423449
}

0 commit comments

Comments
 (0)