Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/river/token/builder/value_tokens.go
4096 views
1
package builder
2
3
import (
4
"fmt"
5
"sort"
6
7
"github.com/grafana/agent/pkg/river/internal/value"
8
"github.com/grafana/agent/pkg/river/scanner"
9
"github.com/grafana/agent/pkg/river/token"
10
)
11
12
// TODO(rfratto): check for optional values
13
14
// Tokenizer is any value which can return a raw set of tokens.
15
type Tokenizer interface {
16
// RiverTokenize returns the raw set of River tokens which are used when
17
// printing out the value with river/token/builder.
18
RiverTokenize() []Token
19
}
20
21
func tokenEncode(val interface{}) []Token {
22
return valueTokens(value.Encode(val))
23
}
24
25
func valueTokens(v value.Value) []Token {
26
var toks []Token
27
28
// If v is a Tokenizer, allow it to override what tokens get generated.
29
if tk, ok := v.Interface().(Tokenizer); ok {
30
return tk.RiverTokenize()
31
}
32
33
switch v.Type() {
34
case value.TypeNull:
35
toks = append(toks, Token{token.NULL, "null"})
36
37
case value.TypeNumber:
38
toks = append(toks, Token{token.NUMBER, v.Number().ToString()})
39
40
case value.TypeString:
41
toks = append(toks, Token{token.STRING, fmt.Sprintf("%q", v.Text())})
42
43
case value.TypeBool:
44
toks = append(toks, Token{token.STRING, fmt.Sprintf("%v", v.Bool())})
45
46
case value.TypeArray:
47
toks = append(toks, Token{token.LBRACK, ""})
48
elems := v.Len()
49
for i := 0; i < elems; i++ {
50
elem := v.Index(i)
51
52
toks = append(toks, valueTokens(elem)...)
53
if i+1 < elems {
54
toks = append(toks, Token{token.COMMA, ""})
55
}
56
}
57
toks = append(toks, Token{token.RBRACK, ""})
58
59
case value.TypeObject:
60
toks = append(toks, Token{token.LCURLY, ""}, Token{token.LITERAL, "\n"})
61
62
keys := v.Keys()
63
64
// If v isn't an ordered object (i.e., a go map), sort the keys so they
65
// have a deterministic print order.
66
if !v.OrderedKeys() {
67
sort.Strings(keys)
68
}
69
70
for i := 0; i < len(keys); i++ {
71
if isValidIdentifier(keys[i]) {
72
toks = append(toks, Token{token.IDENT, keys[i]})
73
} else {
74
toks = append(toks, Token{token.STRING, fmt.Sprintf("%q", keys[i])})
75
}
76
77
field, _ := v.Key(keys[i])
78
toks = append(toks, Token{token.ASSIGN, ""})
79
toks = append(toks, valueTokens(field)...)
80
toks = append(toks, Token{token.COMMA, ""}, Token{token.LITERAL, "\n"})
81
}
82
toks = append(toks, Token{token.RCURLY, ""})
83
84
case value.TypeFunction:
85
toks = append(toks, Token{token.LITERAL, v.Describe()})
86
87
case value.TypeCapsule:
88
toks = append(toks, Token{token.LITERAL, v.Describe()})
89
90
default:
91
panic(fmt.Sprintf("river/token/builder: unrecognized value type %q", v.Type()))
92
}
93
94
return toks
95
}
96
97
func isValidIdentifier(in string) bool {
98
s := scanner.New(nil, []byte(in), nil, 0)
99
_, tok, lit := s.Scan()
100
return tok == token.IDENT && lit == in
101
}
102
103