Skip to content

Commit

Permalink
add encoder support Int64ToString
Browse files Browse the repository at this point in the history
  • Loading branch information
period331 committed Dec 25, 2024
1 parent 1db3dd0 commit 7ad6f70
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 24 deletions.
3 changes: 2 additions & 1 deletion api.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ type Config struct {
// Encode Infinity or Nan float into `null`, instead of returning an error.
EncodeNullForInfOrNan bool

// Uint64 into strings on Marshal
// Uint64 or Int64 into strings on Marshal
Uint64ToString bool
Int64ToString bool
}

var (
Expand Down
38 changes: 26 additions & 12 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1226,13 +1226,14 @@ func TestMarshalInfOrNan(t *testing.T) {
}
}

func TestUint64ToString(t *testing.T) {
func TestUint64OrInt64ToString(t *testing.T) {
int64ptr := int64(432556670863027541)
uint64ptr := uint64(12372850276778298372)
cases := []struct {
name string
val interface{}
exceptTrue string
exceptUint64ToStr string
exceptInt64ToStr string
exceptFalse string
}{
{
Expand All @@ -1242,7 +1243,8 @@ func TestUint64ToString(t *testing.T) {
"int64": int64(34),
"uint64": uint64(56),
},
exceptTrue: `{"int":12,"int64":34,"uint64":"56"}`,
exceptUint64ToStr: `{"int":12,"int64":34,"uint64":"56"}`,
exceptInt64ToStr: `{"int":12,"int64":"34","uint64":56}`,
exceptFalse: `{"int":12,"int64":34,"uint64":56}`,
},
{
Expand All @@ -1252,7 +1254,8 @@ func TestUint64ToString(t *testing.T) {
int64(34): int64(34),
int64(56): uint64(56),
},
exceptTrue: `{"12":12,"34":34,"56":"56"}`,
exceptUint64ToStr: `{"12":12,"34":34,"56":"56"}`,
exceptInt64ToStr: `{"12":12,"34":"34","56":56}`,
exceptFalse: `{"12":12,"34":34,"56":56}`,
},
{
Expand All @@ -1262,7 +1265,8 @@ func TestUint64ToString(t *testing.T) {
uint64(34): int64(34),
uint64(56): uint64(56),
},
exceptTrue: `{"12":12,"34":34,"56":"56"}`,
exceptUint64ToStr: `{"12":12,"34":34,"56":"56"}`,
exceptInt64ToStr: `{"12":12,"34":"34","56":56}`,
exceptFalse: `{"12":12,"34":34,"56":56}`,
},
{
Expand All @@ -1276,27 +1280,31 @@ func TestUint64ToString(t *testing.T) {
Int64: int64(34),
Uint64: uint64(56),
},
exceptTrue: `{"int":12,"int64":34,"uint64":"56"}`,
exceptUint64ToStr: `{"int":12,"int64":34,"uint64":"56"}`,
exceptInt64ToStr: `{"int":12,"int64":"34","uint64":56}`,
exceptFalse: `{"int":12,"int64":34,"uint64":56}`,
},
{
name: "normal_slice",
val: []interface{}{
int(12), int64(34), uint64(56),
},
exceptTrue: `[12,34,"56"]`,
exceptUint64ToStr: `[12,34,"56"]`,
exceptInt64ToStr: `[12,"34",56]`,
exceptFalse: `[12,34,56]`,
},
{
name: "single_int64",
val: int64(34),
exceptTrue: `34`,
exceptUint64ToStr: `34`,
exceptInt64ToStr: `"34"`,
exceptFalse: `34`,
},
{
name: "single_uint64",
val: uint64(56),
exceptTrue: `"56"`,
exceptUint64ToStr: `"56"`,
exceptInt64ToStr: `56`,
exceptFalse: `56`,
},
{
Expand All @@ -1314,8 +1322,10 @@ func TestUint64ToString(t *testing.T) {
Int64: int64(123),
Uint64: uint64(456),
}}},
exceptTrue: `{"Map":{"val":{"Int64Ptr":432556670863027541,` +
exceptUint64ToStr: `{"Map":{"val":{"Int64Ptr":432556670863027541,` +
`"Uint64Ptr":"12372850276778298372","Int64":123,"Uint64":"456"}}}`,
exceptInt64ToStr: `{"Map":{"val":{"Int64Ptr":"432556670863027541",` +
`"Uint64Ptr":12372850276778298372,"Int64":"123","Uint64":456}}}`,
exceptFalse: `{"Map":{"val":{"Int64Ptr":432556670863027541,` +
`"Uint64Ptr":12372850276778298372,"Int64":123,"Uint64":456}}}`,
},
Expand All @@ -1333,9 +1343,13 @@ func TestUint64ToString(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
b, e := Config{Uint64ToString: true}.Froze().Marshal(c.val)
assert.Nil(t, e)
check(t, c.exceptTrue, b)
check(t, c.exceptUint64ToStr, b)

b, e = Config{Uint64ToString: false}.Froze().Marshal(c.val)
b, e = Config{Int64ToString: true}.Froze().Marshal(c.val)
assert.Nil(t, e)
check(t, c.exceptInt64ToStr, b)

b, e = Config{}.Froze().Marshal(c.val)
assert.Nil(t, e)
check(t, c.exceptFalse, b)
})
Expand Down
3 changes: 2 additions & 1 deletion encoder/encoder_native.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ const (
// Encode Infinity or Nan float into `null`, instead of returning an error.
EncodeNullForInfOrNan Options = encoder.EncodeNullForInfOrNan

// Uint64 into strings on Marshal
// Uint64 or Int64 into strings on Marshal
Uint64ToString Options = encoder.Uint64ToString
Int64ToString Options = encoder.Int64ToString
)


Expand Down
1 change: 1 addition & 0 deletions internal/encoder/alg/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
BitNoEncoderNewline
BitEncodeNullForInfOrNan
BitUint64ToString
BitInt64ToString

BitPointerValue = 63
)
4 changes: 2 additions & 2 deletions internal/encoder/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func (self *Compiler) compileOps(p *ir.Program, sp int, vt reflect.Type) {
case reflect.Int64:
p.Add(ir.OP_i64)
case reflect.Uint:
p.Add(ir.OP_uint(), ir.OP_ui)
p.Add(ir.OP_uint(), ir.OP_u)
case reflect.Uint8:
p.Add(ir.OP_u8)
case reflect.Uint16:
Expand Down Expand Up @@ -311,7 +311,7 @@ func (self *Compiler) compileMapBodyTextKey(p *ir.Program, vk reflect.Type) {
case reflect.Int64:
p.Key(ir.OP_i64)
case reflect.Uint:
p.Key(ir.OP_uint(), ir.OP_ui)
p.Key(ir.OP_uint(), ir.OP_u)
case reflect.Uint8:
p.Key(ir.OP_u8)
case reflect.Uint16:
Expand Down
3 changes: 2 additions & 1 deletion internal/encoder/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ const (
// Encode Infinity or Nan float into `null`, instead of returning an error.
EncodeNullForInfOrNan Options = 1 << alg.BitEncodeNullForInfOrNan

// Uint64 into strings on Marshal
// Uint64 or Int64 into strings on Marshal
Uint64ToString Options = 1 << alg.BitUint64ToString
Int64ToString Options = 1 << alg.BitInt64ToString
)

// Encoder represents a specific set of encoder configurations.
Expand Down
4 changes: 2 additions & 2 deletions internal/encoder/ir/op.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const (
OP_u16
OP_u32
OP_u64
OP_ui
OP_u
OP_f32
OP_f64
OP_str
Expand Down Expand Up @@ -106,7 +106,7 @@ var OpNames = [256]string{
OP_u16: "u16",
OP_u32: "u32",
OP_u64: "u64",
OP_ui: "ui",
OP_u: "u",
OP_f32: "f32",
OP_f64: "f64",
OP_str: "str",
Expand Down
15 changes: 12 additions & 3 deletions internal/encoder/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,17 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
v := *(*int32)(p)
buf = alg.I64toa(buf, int64(v))
case ir.OP_i64:
v := *(*int64)(p)
buf = alg.I64toa(buf, int64(v))
if ins.CompatOp() == ir.OP_i ||
ins.IsMapKey() ||
flags&(1<<alg.BitInt64ToString) == 0 {
v := *(*int64)(p)
buf = alg.I64toa(buf, int64(v))
continue
}
buf = append(buf, '"')
v := *(*uint64)(p)
buf = alg.U64toa(buf, uint64(v))
buf = append(buf, '"')
case ir.OP_u8:
v := *(*uint8)(p)
buf = alg.U64toa(buf, uint64(v))
Expand All @@ -152,7 +161,7 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
v := *(*uint32)(p)
buf = alg.U64toa(buf, uint64(v))
case ir.OP_u64:
if ins.CompatOp() == ir.OP_i ||
if ins.CompatOp() == ir.OP_u ||
ins.IsMapKey() ||
flags&(1<<alg.BitUint64ToString) == 0 {
v := *(*uint64)(p)
Expand Down
18 changes: 16 additions & 2 deletions internal/encoder/x86/assembler_regabi_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,8 +844,22 @@ func (self *Assembler) _asm_OP_i32(_ *ir.Instr) {
self.store_int(17, _F_i64toa, "MOVLQSX")
}

func (self *Assembler) _asm_OP_i64(_ *ir.Instr) {
func (self *Assembler) _asm_OP_i64(i *ir.Instr) {
if i.CompatOp() == ir.OP_i || i.IsMapKey() {
self.store_int(21, _F_i64toa, "MOVQ")
return
}
self.Emit("BTQ", jit.Imm(int64(alg.BitInt64ToString)), _ARG_fv)
self.Sjmp("JC", "_i64_to_string{n}")
self.store_int(21, _F_i64toa, "MOVQ")
self.Sjmp("JMP", "_i64_to_string_end{n}")
self.Link("_i64_to_string{n}")

self.add_char('"')
self.store_int(21, _F_i64toa, "MOVQ")
self.add_char('"')
self.Link("_i64_to_string_end{n}")

}

func (self *Assembler) _asm_OP_u8(_ *ir.Instr) {
Expand All @@ -861,7 +875,7 @@ func (self *Assembler) _asm_OP_u32(_ *ir.Instr) {
}

func (self *Assembler) _asm_OP_u64(i *ir.Instr) {
if i.CompatOp() == ir.OP_i || i.IsMapKey() {
if i.CompatOp() == ir.OP_u || i.IsMapKey() {
self.store_int(20, _F_u64toa, "MOVQ")
return
}
Expand Down
3 changes: 3 additions & 0 deletions sonic.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ func (cfg Config) Froze() API {
if cfg.Uint64ToString {
api.encoderOpts |= encoder.Uint64ToString
}
if cfg.Int64ToString {
api.encoderOpts |= encoder.Int64ToString
}

// configure decoder options:
if cfg.NoValidateJSONSkip {
Expand Down

0 comments on commit 7ad6f70

Please sign in to comment.