Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/river/internal/value/number_value.go
4096 views
1
package value
2
3
import (
4
"math"
5
"reflect"
6
"strconv"
7
)
8
9
var (
10
nativeIntBits = reflect.TypeOf(int(0)).Bits()
11
nativeUintBits = reflect.TypeOf(uint(0)).Bits()
12
)
13
14
// NumberKind categorizes a type of Go number.
15
type NumberKind uint8
16
17
const (
18
// NumberKindInt represents an int-like type (e.g., int, int8, etc.).
19
NumberKindInt NumberKind = iota
20
// NumberKindUint represents a uint-like type (e.g., uint, uint8, etc.).
21
NumberKindUint
22
// NumberKindFloat represents both float32 and float64.
23
NumberKindFloat
24
)
25
26
// makeNumberKind converts a Go kind to a River kind.
27
func makeNumberKind(k reflect.Kind) NumberKind {
28
switch k {
29
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
30
return NumberKindInt
31
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
32
return NumberKindUint
33
case reflect.Float32, reflect.Float64:
34
return NumberKindFloat
35
default:
36
panic("river/value: makeNumberKind called with unsupported Kind value")
37
}
38
}
39
40
// Number is a generic representation of Go numbers. It is intended to be
41
// created on the fly for numerical operations when the real number type is not
42
// known.
43
type Number struct {
44
// Value holds the raw data for the number. Note that for numberKindFloat,
45
// value is the raw bits of the float64 and must be converted back to a
46
// float64 before it can be used.
47
value uint64
48
49
bits uint8 // 8, 16, 32, 64, used for overflow checking
50
k NumberKind // int, uint, float
51
}
52
53
func newNumberValue(v reflect.Value) Number {
54
var (
55
val uint64
56
bits int
57
nk NumberKind
58
)
59
60
switch v.Kind() {
61
case reflect.Int:
62
val, bits, nk = uint64(v.Int()), nativeIntBits, NumberKindInt
63
case reflect.Int8:
64
val, bits, nk = uint64(v.Int()), 8, NumberKindInt
65
case reflect.Int16:
66
val, bits, nk = uint64(v.Int()), 16, NumberKindInt
67
case reflect.Int32:
68
val, bits, nk = uint64(v.Int()), 32, NumberKindInt
69
case reflect.Int64:
70
val, bits, nk = uint64(v.Int()), 64, NumberKindInt
71
case reflect.Uint:
72
val, bits, nk = v.Uint(), nativeUintBits, NumberKindUint
73
case reflect.Uint8:
74
val, bits, nk = v.Uint(), 8, NumberKindUint
75
case reflect.Uint16:
76
val, bits, nk = v.Uint(), 16, NumberKindUint
77
case reflect.Uint32:
78
val, bits, nk = v.Uint(), 32, NumberKindUint
79
case reflect.Uint64:
80
val, bits, nk = v.Uint(), 64, NumberKindUint
81
case reflect.Float32:
82
val, bits, nk = math.Float64bits(v.Float()), 32, NumberKindFloat
83
case reflect.Float64:
84
val, bits, nk = math.Float64bits(v.Float()), 64, NumberKindFloat
85
default:
86
panic("river/value: unrecognized Go number type " + v.Kind().String())
87
}
88
89
return Number{val, uint8(bits), nk}
90
}
91
92
// Kind returns the Number's NumberKind.
93
func (nv Number) Kind() NumberKind { return nv.k }
94
95
// Int converts the Number into an int64.
96
func (nv Number) Int() int64 {
97
if nv.k == NumberKindFloat {
98
return int64(math.Float64frombits(nv.value))
99
}
100
return int64(nv.value)
101
}
102
103
// Uint converts the Number into a uint64.
104
func (nv Number) Uint() uint64 {
105
if nv.k == NumberKindFloat {
106
return uint64(math.Float64frombits(nv.value))
107
}
108
return nv.value
109
}
110
111
// Float converts the Number into a float64.
112
func (nv Number) Float() float64 {
113
switch nv.k {
114
case NumberKindInt:
115
// Convert nv.value to an int64 before converting to a float64 so the sign
116
// flag gets handled correctly.
117
return float64(int64(nv.value))
118
case NumberKindFloat:
119
return math.Float64frombits(nv.value)
120
}
121
return float64(nv.value)
122
}
123
124
// ToString converts the Number to a string.
125
func (nv Number) ToString() string {
126
switch nv.k {
127
case NumberKindUint:
128
return strconv.FormatUint(nv.value, 10)
129
case NumberKindInt:
130
return strconv.FormatInt(int64(nv.value), 10)
131
case NumberKindFloat:
132
return strconv.FormatFloat(math.Float64frombits(nv.value), 'f', -1, 64)
133
}
134
panic("river/value: unreachable")
135
}
136
137