1package 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}
113