blob: 98d45c1ec25500f9d7f7c944286e26bbc5d321ae [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001package jsoniter
2
3import (
4 "encoding/json"
5 "github.com/modern-go/reflect2"
6 "strconv"
7 "unsafe"
8)
9
10type Number string
11
12// String returns the literal text of the number.
13func (n Number) String() string { return string(n) }
14
15// Float64 returns the number as a float64.
16func (n Number) Float64() (float64, error) {
17 return strconv.ParseFloat(string(n), 64)
18}
19
20// Int64 returns the number as an int64.
21func (n Number) Int64() (int64, error) {
22 return strconv.ParseInt(string(n), 10, 64)
23}
24
25func CastJsonNumber(val interface{}) (string, bool) {
26 switch typedVal := val.(type) {
27 case json.Number:
28 return string(typedVal), true
29 case Number:
30 return string(typedVal), true
31 }
32 return "", false
33}
34
35var jsonNumberType = reflect2.TypeOfPtr((*json.Number)(nil)).Elem()
36var jsoniterNumberType = reflect2.TypeOfPtr((*Number)(nil)).Elem()
37
38func createDecoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValDecoder {
39 if typ.AssignableTo(jsonNumberType) {
40 return &jsonNumberCodec{}
41 }
42 if typ.AssignableTo(jsoniterNumberType) {
43 return &jsoniterNumberCodec{}
44 }
45 return nil
46}
47
48func createEncoderOfJsonNumber(ctx *ctx, typ reflect2.Type) ValEncoder {
49 if typ.AssignableTo(jsonNumberType) {
50 return &jsonNumberCodec{}
51 }
52 if typ.AssignableTo(jsoniterNumberType) {
53 return &jsoniterNumberCodec{}
54 }
55 return nil
56}
57
58type jsonNumberCodec struct {
59}
60
61func (codec *jsonNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
62 switch iter.WhatIsNext() {
63 case StringValue:
64 *((*json.Number)(ptr)) = json.Number(iter.ReadString())
65 case NilValue:
66 iter.skipFourBytes('n', 'u', 'l', 'l')
67 *((*json.Number)(ptr)) = ""
68 default:
69 *((*json.Number)(ptr)) = json.Number([]byte(iter.readNumberAsString()))
70 }
71}
72
73func (codec *jsonNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
74 number := *((*json.Number)(ptr))
75 if len(number) == 0 {
76 stream.writeByte('0')
77 } else {
78 stream.WriteRaw(string(number))
79 }
80}
81
82func (codec *jsonNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
83 return len(*((*json.Number)(ptr))) == 0
84}
85
86type jsoniterNumberCodec struct {
87}
88
89func (codec *jsoniterNumberCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
90 switch iter.WhatIsNext() {
91 case StringValue:
92 *((*Number)(ptr)) = Number(iter.ReadString())
93 case NilValue:
94 iter.skipFourBytes('n', 'u', 'l', 'l')
95 *((*Number)(ptr)) = ""
96 default:
97 *((*Number)(ptr)) = Number([]byte(iter.readNumberAsString()))
98 }
99}
100
101func (codec *jsoniterNumberCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
102 number := *((*Number)(ptr))
103 if len(number) == 0 {
104 stream.writeByte('0')
105 } else {
106 stream.WriteRaw(string(number))
107 }
108}
109
110func (codec *jsoniterNumberCodec) IsEmpty(ptr unsafe.Pointer) bool {
111 return len(*((*Number)(ptr))) == 0
112}