Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/river/internal/value/value.go
4096 views
1
// Package value holds the internal representation for River values. River
2
// values act as a lightweight wrapper around reflect.Value.
3
package value
4
5
import (
6
"encoding"
7
"fmt"
8
"reflect"
9
"strconv"
10
"strings"
11
"time"
12
13
"github.com/grafana/agent/pkg/river/internal/reflectutil"
14
)
15
16
// Go types used throughout the package.
17
var (
18
goAny = reflect.TypeOf((*interface{})(nil)).Elem()
19
goString = reflect.TypeOf(string(""))
20
goByteSlice = reflect.TypeOf([]byte(nil))
21
goError = reflect.TypeOf((*error)(nil)).Elem()
22
goTextMarshaler = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
23
goTextUnmarshaler = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
24
goStructWrapper = reflect.TypeOf(structWrapper{})
25
goCapsule = reflect.TypeOf((*Capsule)(nil)).Elem()
26
goDuration = reflect.TypeOf((time.Duration)(0))
27
goDurationPtr = reflect.TypeOf((*time.Duration)(nil))
28
goRiverDecoder = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
29
goRawRiverFunc = reflect.TypeOf((RawFunction)(nil))
30
goRiverValue = reflect.TypeOf(Null)
31
)
32
33
// NOTE(rfratto): This package is extremely sensitive to performance, so
34
// changes should be made with caution; run benchmarks when changing things.
35
//
36
// Value is optimized to be as small as possible and exist fully on the stack.
37
// This allows many values to avoid allocations, with the exception of creating
38
// arrays and objects.
39
40
// Value represents a River value.
41
type Value struct {
42
rv reflect.Value
43
ty Type
44
}
45
46
// Null is the null value.
47
var Null = Value{}
48
49
// Uint returns a Value from a uint64.
50
func Uint(u uint64) Value { return Value{rv: reflect.ValueOf(u), ty: TypeNumber} }
51
52
// Int returns a Value from an int64.
53
func Int(i int64) Value { return Value{rv: reflect.ValueOf(i), ty: TypeNumber} }
54
55
// Float returns a Value from a float64.
56
func Float(f float64) Value { return Value{rv: reflect.ValueOf(f), ty: TypeNumber} }
57
58
// String returns a Value from a string.
59
func String(s string) Value { return Value{rv: reflect.ValueOf(s), ty: TypeString} }
60
61
// Bool returns a Value from a bool.
62
func Bool(b bool) Value { return Value{rv: reflect.ValueOf(b), ty: TypeBool} }
63
64
// Object returns a new value from m. A copy of m is made for producing the
65
// Value.
66
func Object(m map[string]Value) Value {
67
return Value{
68
rv: reflect.ValueOf(m),
69
ty: TypeObject,
70
}
71
}
72
73
// Array creates an array from the given values. A copy of the vv slice is made
74
// for producing the Value.
75
func Array(vv ...Value) Value {
76
return Value{
77
rv: reflect.ValueOf(vv),
78
ty: TypeArray,
79
}
80
}
81
82
// Func makes a new function Value from f. Func panics if f does not map to a
83
// River function.
84
func Func(f interface{}) Value {
85
rv := reflect.ValueOf(f)
86
if RiverType(rv.Type()) != TypeFunction {
87
panic("river/value: Func called with non-function type")
88
}
89
return Value{rv: rv, ty: TypeFunction}
90
}
91
92
// Encapsulate creates a new Capsule value from v. Encapsulate panics if v does
93
// not map to a River capsule.
94
func Encapsulate(v interface{}) Value {
95
rv := reflect.ValueOf(v)
96
if RiverType(rv.Type()) != TypeCapsule {
97
panic("river/value: Capsule called with non-capsule type")
98
}
99
return Value{rv: rv, ty: TypeCapsule}
100
}
101
102
// Encode creates a new Value from v. If v is a pointer, v must be considered
103
// immutable and not change while the Value is used.
104
func Encode(v interface{}) Value {
105
if v == nil {
106
return Null
107
}
108
return makeValue(reflect.ValueOf(v))
109
}
110
111
// FromRaw converts a reflect.Value into a River Value. It is useful to prevent
112
// downcasting an interface into an any.
113
func FromRaw(v reflect.Value) Value {
114
return makeValue(v)
115
}
116
117
// Type returns the River type for the value.
118
func (v Value) Type() Type { return v.ty }
119
120
// Describe returns a descriptive type name for the value. For capsule values,
121
// this prints the underlying Go type name. For other values, it prints the
122
// normal River type.
123
func (v Value) Describe() string {
124
if v.ty != TypeCapsule {
125
return v.ty.String()
126
}
127
return fmt.Sprintf("capsule(%q)", v.rv.Type())
128
}
129
130
// Bool returns the boolean value for v. It panics if v is not a bool.
131
func (v Value) Bool() bool {
132
if v.ty != TypeBool {
133
panic("river/value: Bool called on non-bool type")
134
}
135
return v.rv.Bool()
136
}
137
138
// Number returns a Number value for v. It panics if v is not a Number.
139
func (v Value) Number() Number {
140
if v.ty != TypeNumber {
141
panic("river/value: Number called on non-number type")
142
}
143
return newNumberValue(v.rv)
144
}
145
146
// Int returns an int value for v. It panics if v is not a number.
147
func (v Value) Int() int64 {
148
if v.ty != TypeNumber {
149
panic("river/value: Int called on non-number type")
150
}
151
switch makeNumberKind(v.rv.Kind()) {
152
case NumberKindInt:
153
return v.rv.Int()
154
case NumberKindUint:
155
return int64(v.rv.Uint())
156
case NumberKindFloat:
157
return int64(v.rv.Float())
158
}
159
panic("river/value: unreachable")
160
}
161
162
// Uint returns an uint value for v. It panics if v is not a number.
163
func (v Value) Uint() uint64 {
164
if v.ty != TypeNumber {
165
panic("river/value: Uint called on non-number type")
166
}
167
switch makeNumberKind(v.rv.Kind()) {
168
case NumberKindInt:
169
return uint64(v.rv.Int())
170
case NumberKindUint:
171
return v.rv.Uint()
172
case NumberKindFloat:
173
return uint64(v.rv.Float())
174
}
175
panic("river/value: unreachable")
176
}
177
178
// Float returns a float value for v. It panics if v is not a number.
179
func (v Value) Float() float64 {
180
if v.ty != TypeNumber {
181
panic("river/value: Float called on non-number type")
182
}
183
switch makeNumberKind(v.rv.Kind()) {
184
case NumberKindInt:
185
return float64(v.rv.Int())
186
case NumberKindUint:
187
return float64(v.rv.Uint())
188
case NumberKindFloat:
189
return v.rv.Float()
190
}
191
panic("river/value: unreachable")
192
}
193
194
// Text returns a string value of v. It panics if v is not a string.
195
func (v Value) Text() string {
196
if v.ty != TypeString {
197
panic("river/value: Text called on non-string type")
198
}
199
200
// Attempt to get an address to v.rv for interface checking.
201
//
202
// The normal v.rv value is used for other checks.
203
addrRV := v.rv
204
if addrRV.CanAddr() {
205
addrRV = addrRV.Addr()
206
}
207
switch {
208
case addrRV.Type().Implements(goTextMarshaler):
209
// TODO(rfratto): what should we do if this fails?
210
text, _ := addrRV.Interface().(encoding.TextMarshaler).MarshalText()
211
return string(text)
212
213
case v.rv.Type() == goDuration:
214
// Special case: v.rv is a duration and its String method should be used.
215
return v.rv.Interface().(time.Duration).String()
216
217
default:
218
return v.rv.String()
219
}
220
}
221
222
// Len returns the length of v. Panics if v is not an array or object.
223
func (v Value) Len() int {
224
switch v.ty {
225
case TypeArray:
226
return v.rv.Len()
227
case TypeObject:
228
switch {
229
case v.rv.Type() == goStructWrapper:
230
return v.rv.Interface().(structWrapper).Len()
231
case v.rv.Kind() == reflect.Array, v.rv.Kind() == reflect.Slice: // Array of labeled blocks
232
return v.rv.Len()
233
case v.rv.Kind() == reflect.Struct:
234
return getCachedTags(v.rv.Type()).Len()
235
case v.rv.Kind() == reflect.Map:
236
return v.rv.Len()
237
}
238
}
239
panic("river/value: Len called on non-array and non-object value")
240
}
241
242
// Index returns index i of the Value. Panics if the value is not an array or
243
// if it is out of bounds of the array's size.
244
func (v Value) Index(i int) Value {
245
if v.ty != TypeArray {
246
panic("river/value: Index called on non-array value")
247
}
248
return makeValue(v.rv.Index(i))
249
}
250
251
// Interface returns the underlying Go value for the Value.
252
func (v Value) Interface() interface{} {
253
if v.ty == TypeNull {
254
return nil
255
}
256
return v.rv.Interface()
257
}
258
259
// Reflect returns the raw reflection value backing v.
260
func (v Value) Reflect() reflect.Value { return v.rv }
261
262
// makeValue converts a reflect value into a Value, dereferencing any pointers or
263
// interface{} values.
264
func makeValue(v reflect.Value) Value {
265
// Early check: if v is interface{}, we need to deference it to get the
266
// concrete value.
267
if v.IsValid() && v.Type() == goAny {
268
v = v.Elem()
269
}
270
271
// Special case: a reflect.Value may be a value.Value when it's coming from a
272
// River array or object. We can unwrap the inner value here before
273
// continuing.
274
if v.IsValid() && v.Type() == goRiverValue {
275
// Unwrap the inner value.
276
v = v.Interface().(Value).rv
277
}
278
279
// Before we get the River type of the Value, we need to see if it's possible
280
// to get a pointer to v. This ensures that if v is a non-pointer field of an
281
// addressable struct, still detect the type of v as if it was a pointer.
282
if v.CanAddr() {
283
v = v.Addr()
284
}
285
286
if !v.IsValid() {
287
return Null
288
}
289
riverType := RiverType(v.Type())
290
291
// Finally, deference the pointer fully and use the type we detected.
292
for v.Kind() == reflect.Pointer {
293
if v.IsNil() {
294
return Null
295
}
296
v = v.Elem()
297
}
298
return Value{rv: v, ty: riverType}
299
}
300
301
// OrderedKeys reports if v represents an object with consistently ordered
302
// keys. It panics if v is not an object.
303
func (v Value) OrderedKeys() bool {
304
if v.ty != TypeObject {
305
panic("river/value: OrderedKeys called on non-object value")
306
}
307
308
// Maps are the only type of unordered River object, since their keys can't
309
// be iterated over in a deterministic order. Every other type of River
310
// object comes from a struct or a slice where the order of keys stays the
311
// same.
312
return v.rv.Kind() != reflect.Map
313
}
314
315
// Keys returns the keys in v in unspecified order. It panics if v is not an
316
// object.
317
func (v Value) Keys() []string {
318
if v.ty != TypeObject {
319
panic("river/value: Keys called on non-object value")
320
}
321
322
switch {
323
case v.rv.Type() == goStructWrapper:
324
return v.rv.Interface().(structWrapper).Keys()
325
326
case v.rv.Kind() == reflect.Struct:
327
return wrapStruct(v.rv, true).Keys()
328
329
case v.rv.Kind() == reflect.Array, v.rv.Kind() == reflect.Slice:
330
// List of labeled blocks.
331
labelField, _ := getCachedTags(v.rv.Type().Elem()).LabelField()
332
333
keys := make([]string, v.rv.Len())
334
for i := range keys {
335
keys[i] = reflectutil.Get(v.rv.Index(i), labelField).String()
336
}
337
return keys
338
339
case v.rv.Kind() == reflect.Map:
340
reflectKeys := v.rv.MapKeys()
341
res := make([]string, len(reflectKeys))
342
for i, rk := range reflectKeys {
343
res[i] = rk.String()
344
}
345
return res
346
}
347
348
panic("river/value: unreachable")
349
}
350
351
// Key returns the value for a key in v. It panics if v is not an object. ok
352
// will be false if the key did not exist in the object.
353
func (v Value) Key(key string) (index Value, ok bool) {
354
if v.ty != TypeObject {
355
panic("river/value: Key called on non-object value")
356
}
357
358
switch {
359
case v.rv.Type() == goStructWrapper:
360
return v.rv.Interface().(structWrapper).Key(key)
361
case v.rv.Kind() == reflect.Struct:
362
// We return the struct with the label intact.
363
return wrapStruct(v.rv, true).Key(key)
364
case v.rv.Kind() == reflect.Map:
365
val := v.rv.MapIndex(reflect.ValueOf(key))
366
if !val.IsValid() {
367
return Null, false
368
}
369
return makeValue(val), true
370
371
case v.rv.Kind() == reflect.Slice, v.rv.Kind() == reflect.Array:
372
// List of labeled blocks.
373
labelField, _ := getCachedTags(v.rv.Type().Elem()).LabelField()
374
375
for i := 0; i < v.rv.Len(); i++ {
376
elem := v.rv.Index(i)
377
378
label := reflectutil.Get(elem, labelField).String()
379
if label == key {
380
// We discard the label since the key here represents the label value.
381
ws := wrapStruct(elem, false)
382
return ws.Value(), true
383
}
384
}
385
default:
386
panic("river/value: unreachable")
387
}
388
389
return
390
}
391
392
// Call invokes a function value with the provided arguments. It panics if v is
393
// not a function. If v is a variadic function, args should be the full flat
394
// list of arguments.
395
//
396
// An ArgError will be returned if one of the arguments is invalid. An Error
397
// will be returned if the function call returns an error or if the number of
398
// arguments doesn't match.
399
func (v Value) Call(args ...Value) (Value, error) {
400
if v.ty != TypeFunction {
401
panic("river/value: Call called on non-function type")
402
}
403
404
if v.rv.Type() == goRawRiverFunc {
405
return v.rv.Interface().(RawFunction)(v, args...)
406
}
407
408
var (
409
variadic = v.rv.Type().IsVariadic()
410
expectedArgs = v.rv.Type().NumIn()
411
)
412
413
if variadic && len(args) < expectedArgs-1 {
414
return Null, Error{
415
Value: v,
416
Inner: fmt.Errorf("expected at least %d args, got %d", expectedArgs-1, len(args)),
417
}
418
} else if !variadic && len(args) != expectedArgs {
419
return Null, Error{
420
Value: v,
421
Inner: fmt.Errorf("expected %d args, got %d", expectedArgs, len(args)),
422
}
423
}
424
425
reflectArgs := make([]reflect.Value, len(args))
426
for i, arg := range args {
427
var argVal reflect.Value
428
if variadic && i >= expectedArgs-1 {
429
argType := v.rv.Type().In(expectedArgs - 1).Elem()
430
argVal = reflect.New(argType).Elem()
431
} else {
432
argType := v.rv.Type().In(i)
433
argVal = reflect.New(argType).Elem()
434
}
435
436
var d decoder
437
if err := d.decode(arg, argVal); err != nil {
438
return Null, ArgError{
439
Function: v,
440
Argument: arg,
441
Index: i,
442
Inner: err,
443
}
444
}
445
446
reflectArgs[i] = argVal
447
}
448
449
outs := v.rv.Call(reflectArgs)
450
switch len(outs) {
451
case 1:
452
return makeValue(outs[0]), nil
453
case 2:
454
// When there's 2 return values, the second is always an error.
455
err, _ := outs[1].Interface().(error)
456
if err != nil {
457
return Null, Error{Value: v, Inner: err}
458
}
459
return makeValue(outs[0]), nil
460
461
default:
462
// It's not possible to reach here; we enforce that function values always
463
// have 1 or 2 return values.
464
panic("river/value: unreachable")
465
}
466
}
467
468
func convertValue(val Value, toType Type) (Value, error) {
469
// TODO(rfratto): Use vm benchmarks to see if making this a method on Value
470
// changes anything.
471
472
fromType := val.Type()
473
474
if fromType == toType {
475
// no-op: val is already the right kind.
476
return val, nil
477
}
478
479
switch fromType {
480
case TypeNumber:
481
switch toType {
482
case TypeString: // number -> string
483
strVal := newNumberValue(val.rv).ToString()
484
return makeValue(reflect.ValueOf(strVal)), nil
485
}
486
487
case TypeString:
488
sourceStr := val.rv.String()
489
490
switch toType {
491
case TypeNumber: // string -> number
492
switch {
493
case sourceStr == "":
494
return Null, TypeError{Value: val, Expected: toType}
495
496
case sourceStr[0] == '-':
497
// String starts with a -; parse as a signed int.
498
parsed, err := strconv.ParseInt(sourceStr, 10, 64)
499
if err != nil {
500
return Null, TypeError{Value: val, Expected: toType}
501
}
502
return Int(parsed), nil
503
case strings.ContainsAny(sourceStr, ".eE"):
504
// String contains something that a floating-point number would use;
505
// convert.
506
parsed, err := strconv.ParseFloat(sourceStr, 64)
507
if err != nil {
508
return Null, TypeError{Value: val, Expected: toType}
509
}
510
return Float(parsed), nil
511
default:
512
// Otherwise, treat the number as an unsigned int.
513
parsed, err := strconv.ParseUint(sourceStr, 10, 64)
514
if err != nil {
515
return Null, TypeError{Value: val, Expected: toType}
516
}
517
return Uint(parsed), nil
518
}
519
}
520
}
521
522
return Null, TypeError{Value: val, Expected: toType}
523
}
524
525
func convertGoNumber(nval Number, target reflect.Type) reflect.Value {
526
switch target.Kind() {
527
case reflect.Int:
528
return reflect.ValueOf(int(nval.Int()))
529
case reflect.Int8:
530
return reflect.ValueOf(int8(nval.Int()))
531
case reflect.Int16:
532
return reflect.ValueOf(int16(nval.Int()))
533
case reflect.Int32:
534
return reflect.ValueOf(int32(nval.Int()))
535
case reflect.Int64:
536
return reflect.ValueOf(nval.Int())
537
case reflect.Uint:
538
return reflect.ValueOf(uint(nval.Uint()))
539
case reflect.Uint8:
540
return reflect.ValueOf(uint8(nval.Uint()))
541
case reflect.Uint16:
542
return reflect.ValueOf(uint16(nval.Uint()))
543
case reflect.Uint32:
544
return reflect.ValueOf(uint32(nval.Uint()))
545
case reflect.Uint64:
546
return reflect.ValueOf(nval.Uint())
547
case reflect.Float32:
548
return reflect.ValueOf(float32(nval.Float()))
549
case reflect.Float64:
550
return reflect.ValueOf(nval.Float())
551
}
552
553
panic("unsupported number conversion")
554
}
555
556