blob: 679009b1a737c02a0d8b1269fa940ba4f402931d [file] [log] [blame]
Joey Armstronge8c091f2023-01-17 16:56:26 -05001// Copyright The OpenTelemetry Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package label
16
17import (
18 "encoding/json"
19 "fmt"
20 "reflect"
21 "strconv"
22 "unsafe"
23
24 "go.opentelemetry.io/otel/internal"
25)
26
27//go:generate stringer -type=Type
28
29// Type describes the type of the data Value holds.
30type Type int
31
32// Value represents the value part in key-value pairs.
33type Value struct {
34 vtype Type
35 numeric uint64
36 stringly string
37 // TODO Lazy value type?
38
39 array interface{}
40}
41
42const (
43 INVALID Type = iota // No value.
44 BOOL // Boolean value, use AsBool() to get it.
45 INT32 // 32 bit signed integral value, use AsInt32() to get it.
46 INT64 // 64 bit signed integral value, use AsInt64() to get it.
47 UINT32 // 32 bit unsigned integral value, use AsUint32() to get it.
48 UINT64 // 64 bit unsigned integral value, use AsUint64() to get it.
49 FLOAT32 // 32 bit floating point value, use AsFloat32() to get it.
50 FLOAT64 // 64 bit floating point value, use AsFloat64() to get it.
51 STRING // String value, use AsString() to get it.
52 ARRAY // Array value of arbitrary type, use AsArray() to get it.
53)
54
55// BoolValue creates a BOOL Value.
56func BoolValue(v bool) Value {
57 return Value{
58 vtype: BOOL,
59 numeric: internal.BoolToRaw(v),
60 }
61}
62
63// Int64Value creates an INT64 Value.
64func Int64Value(v int64) Value {
65 return Value{
66 vtype: INT64,
67 numeric: internal.Int64ToRaw(v),
68 }
69}
70
71// Uint64Value creates a UINT64 Value.
72func Uint64Value(v uint64) Value {
73 return Value{
74 vtype: UINT64,
75 numeric: internal.Uint64ToRaw(v),
76 }
77}
78
79// Float64Value creates a FLOAT64 Value.
80func Float64Value(v float64) Value {
81 return Value{
82 vtype: FLOAT64,
83 numeric: internal.Float64ToRaw(v),
84 }
85}
86
87// Int32Value creates an INT32 Value.
88func Int32Value(v int32) Value {
89 return Value{
90 vtype: INT32,
91 numeric: internal.Int32ToRaw(v),
92 }
93}
94
95// Uint32Value creates a UINT32 Value.
96func Uint32Value(v uint32) Value {
97 return Value{
98 vtype: UINT32,
99 numeric: internal.Uint32ToRaw(v),
100 }
101}
102
103// Float32Value creates a FLOAT32 Value.
104func Float32Value(v float32) Value {
105 return Value{
106 vtype: FLOAT32,
107 numeric: internal.Float32ToRaw(v),
108 }
109}
110
111// StringValue creates a STRING Value.
112func StringValue(v string) Value {
113 return Value{
114 vtype: STRING,
115 stringly: v,
116 }
117}
118
119// IntValue creates either an INT32 or an INT64 Value, depending on whether
120// the int type is 32 or 64 bits wide.
121func IntValue(v int) Value {
122 if unsafe.Sizeof(v) == 4 {
123 return Int32Value(int32(v))
124 }
125 return Int64Value(int64(v))
126}
127
128// UintValue creates either a UINT32 or a UINT64 Value, depending on whether
129// the uint type is 32 or 64 bits wide.
130func UintValue(v uint) Value {
131 if unsafe.Sizeof(v) == 4 {
132 return Uint32Value(uint32(v))
133 }
134 return Uint64Value(uint64(v))
135}
136
137// ArrayValue creates an ARRAY value from an array or slice.
138// Only arrays or slices of bool, int, int32, int64, uint, uint32, uint64,
139// float, float32, float64, or string types are allowed. Specifically, arrays
140// and slices can not contain other arrays, slices, structs, or non-standard
141// types. If the passed value is not an array or slice of these types an
142// INVALID value is returned.
143func ArrayValue(v interface{}) Value {
144 switch reflect.TypeOf(v).Kind() {
145 case reflect.Array, reflect.Slice:
146 // get array type regardless of dimensions
147 typ := reflect.TypeOf(v).Elem()
148 kind := typ.Kind()
149 switch kind {
150 case reflect.Bool, reflect.Int, reflect.Int32, reflect.Int64,
151 reflect.Float32, reflect.Float64, reflect.String,
152 reflect.Uint, reflect.Uint32, reflect.Uint64:
153 val := reflect.ValueOf(v)
154 length := val.Len()
155 frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ)))
156 reflect.Copy(frozen, val)
157 return Value{
158 vtype: ARRAY,
159 array: frozen.Interface(),
160 }
161 default:
162 return Value{vtype: INVALID}
163 }
164 }
165 return Value{vtype: INVALID}
166}
167
168// Type returns a type of the Value.
169func (v Value) Type() Type {
170 return v.vtype
171}
172
173// AsBool returns the bool value. Make sure that the Value's type is
174// BOOL.
175func (v Value) AsBool() bool {
176 return internal.RawToBool(v.numeric)
177}
178
179// AsInt32 returns the int32 value. Make sure that the Value's type is
180// INT32.
181func (v Value) AsInt32() int32 {
182 return internal.RawToInt32(v.numeric)
183}
184
185// AsInt64 returns the int64 value. Make sure that the Value's type is
186// INT64.
187func (v Value) AsInt64() int64 {
188 return internal.RawToInt64(v.numeric)
189}
190
191// AsUint32 returns the uint32 value. Make sure that the Value's type
192// is UINT32.
193func (v Value) AsUint32() uint32 {
194 return internal.RawToUint32(v.numeric)
195}
196
197// AsUint64 returns the uint64 value. Make sure that the Value's type is
198// UINT64.
199func (v Value) AsUint64() uint64 {
200 return internal.RawToUint64(v.numeric)
201}
202
203// AsFloat32 returns the float32 value. Make sure that the Value's
204// type is FLOAT32.
205func (v Value) AsFloat32() float32 {
206 return internal.RawToFloat32(v.numeric)
207}
208
209// AsFloat64 returns the float64 value. Make sure that the Value's
210// type is FLOAT64.
211func (v Value) AsFloat64() float64 {
212 return internal.RawToFloat64(v.numeric)
213}
214
215// AsString returns the string value. Make sure that the Value's type
216// is STRING.
217func (v Value) AsString() string {
218 return v.stringly
219}
220
221// AsArray returns the array Value as an interface{}.
222func (v Value) AsArray() interface{} {
223 return v.array
224}
225
226type unknownValueType struct{}
227
228// AsInterface returns Value's data as interface{}.
229func (v Value) AsInterface() interface{} {
230 switch v.Type() {
231 case ARRAY:
232 return v.AsArray()
233 case BOOL:
234 return v.AsBool()
235 case INT32:
236 return v.AsInt32()
237 case INT64:
238 return v.AsInt64()
239 case UINT32:
240 return v.AsUint32()
241 case UINT64:
242 return v.AsUint64()
243 case FLOAT32:
244 return v.AsFloat32()
245 case FLOAT64:
246 return v.AsFloat64()
247 case STRING:
248 return v.stringly
249 }
250 return unknownValueType{}
251}
252
253// Emit returns a string representation of Value's data.
254func (v Value) Emit() string {
255 switch v.Type() {
256 case ARRAY:
257 return fmt.Sprint(v.array)
258 case BOOL:
259 return strconv.FormatBool(v.AsBool())
260 case INT32:
261 return strconv.FormatInt(int64(v.AsInt32()), 10)
262 case INT64:
263 return strconv.FormatInt(v.AsInt64(), 10)
264 case UINT32:
265 return strconv.FormatUint(uint64(v.AsUint32()), 10)
266 case UINT64:
267 return strconv.FormatUint(v.AsUint64(), 10)
268 case FLOAT32:
269 return fmt.Sprint(v.AsFloat32())
270 case FLOAT64:
271 return fmt.Sprint(v.AsFloat64())
272 case STRING:
273 return v.stringly
274 default:
275 return "unknown"
276 }
277}
278
279// MarshalJSON returns the JSON encoding of the Value.
280func (v Value) MarshalJSON() ([]byte, error) {
281 var jsonVal struct {
282 Type string
283 Value interface{}
284 }
285 jsonVal.Type = v.Type().String()
286 jsonVal.Value = v.AsInterface()
287 return json.Marshal(jsonVal)
288}