1/*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package thrift
18
19import (
20	"math"
21	"strconv"
22)
23
24type Numeric interface {
25	Int64() int64
26	Int32() int32
27	Int16() int16
28	Byte() byte
29	Int() int
30	Float64() float64
31	Float32() float32
32	String() string
33	isNull() bool
34}
35
36type numeric struct {
37	iValue int64
38	dValue float64
39	sValue string
40	isNil  bool
41}
42
43var (
44	INFINITY          Numeric = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false}
45	NEGATIVE_INFINITY Numeric = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false}
46	NAN               Numeric = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false}
47	ZERO              Numeric = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false}
48	NUMERIC_NULL      Numeric = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true}
49)
50
51func NewNumericFromDouble(dValue float64) Numeric {
52	if math.IsInf(dValue, 1) {
53		return INFINITY
54	}
55	if math.IsInf(dValue, -1) {
56		return NEGATIVE_INFINITY
57	}
58	if math.IsNaN(dValue) {
59		return NAN
60	}
61	iValue := int64(dValue)
62	sValue := strconv.FormatFloat(dValue, 'g', 10, 64)
63	isNil := false
64	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
65}
66
67func NewNumericFromFloat(dValue float32) Numeric {
68	if math.IsInf(float64(dValue), 1) {
69		return INFINITY
70	}
71	if math.IsInf(float64(dValue), -1) {
72		return NEGATIVE_INFINITY
73	}
74	if math.IsNaN(float64(dValue)) {
75		return NAN
76	}
77	iValue := int32(dValue)
78	sValue := strconv.FormatFloat(float64(dValue), 'g', 10, 32)
79	isNil := false
80	return &numeric{iValue: int64(iValue), dValue: float64(dValue), sValue: sValue, isNil: isNil}
81}
82
83func NewNumericFromI64(iValue int64) Numeric {
84	dValue := float64(iValue)
85	sValue := strconv.FormatInt(iValue, 10)
86	isNil := false
87	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
88}
89
90func NewNumericFromI32(iValue int32) Numeric {
91	dValue := float64(iValue)
92	sValue := string(iValue)
93	isNil := false
94	return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil}
95}
96
97func NewNumericFromString(sValue string) Numeric {
98	if sValue == INFINITY.String() {
99		return INFINITY
100	}
101	if sValue == NEGATIVE_INFINITY.String() {
102		return NEGATIVE_INFINITY
103	}
104	if sValue == NAN.String() {
105		return NAN
106	}
107	iValue, _ := strconv.ParseInt(sValue, 10, 64)
108	dValue, _ := strconv.ParseFloat(sValue, 64)
109	isNil := len(sValue) == 0
110	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
111}
112
113func NewNumericFromJSONString(sValue string, isNull bool) Numeric {
114	if isNull {
115		return NewNullNumeric()
116	}
117	if sValue == JSON_INFINITY {
118		return INFINITY
119	}
120	if sValue == JSON_NEGATIVE_INFINITY {
121		return NEGATIVE_INFINITY
122	}
123	if sValue == JSON_NAN {
124		return NAN
125	}
126	iValue, _ := strconv.ParseInt(sValue, 10, 64)
127	dValue, _ := strconv.ParseFloat(sValue, 64)
128	return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull}
129}
130
131func NewNullNumeric() Numeric {
132	return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true}
133}
134
135func (p *numeric) Int64() int64 {
136	return p.iValue
137}
138
139func (p *numeric) Int32() int32 {
140	return int32(p.iValue)
141}
142
143func (p *numeric) Int16() int16 {
144	return int16(p.iValue)
145}
146
147func (p *numeric) Byte() byte {
148	return byte(p.iValue)
149}
150
151func (p *numeric) Int() int {
152	return int(p.iValue)
153}
154
155func (p *numeric) Float64() float64 {
156	return p.dValue
157}
158
159func (p *numeric) Float32() float32 {
160	return float32(p.dValue)
161}
162
163func (p *numeric) String() string {
164	return p.sValue
165}
166
167func (p *numeric) isNull() bool {
168	return p.isNil
169}
170