Path: blob/main/pkg/river/token/builder/value_tokens.go
4096 views
package builder12import (3"fmt"4"sort"56"github.com/grafana/agent/pkg/river/internal/value"7"github.com/grafana/agent/pkg/river/scanner"8"github.com/grafana/agent/pkg/river/token"9)1011// TODO(rfratto): check for optional values1213// Tokenizer is any value which can return a raw set of tokens.14type Tokenizer interface {15// RiverTokenize returns the raw set of River tokens which are used when16// printing out the value with river/token/builder.17RiverTokenize() []Token18}1920func tokenEncode(val interface{}) []Token {21return valueTokens(value.Encode(val))22}2324func valueTokens(v value.Value) []Token {25var toks []Token2627// If v is a Tokenizer, allow it to override what tokens get generated.28if tk, ok := v.Interface().(Tokenizer); ok {29return tk.RiverTokenize()30}3132switch v.Type() {33case value.TypeNull:34toks = append(toks, Token{token.NULL, "null"})3536case value.TypeNumber:37toks = append(toks, Token{token.NUMBER, v.Number().ToString()})3839case value.TypeString:40toks = append(toks, Token{token.STRING, fmt.Sprintf("%q", v.Text())})4142case value.TypeBool:43toks = append(toks, Token{token.STRING, fmt.Sprintf("%v", v.Bool())})4445case value.TypeArray:46toks = append(toks, Token{token.LBRACK, ""})47elems := v.Len()48for i := 0; i < elems; i++ {49elem := v.Index(i)5051toks = append(toks, valueTokens(elem)...)52if i+1 < elems {53toks = append(toks, Token{token.COMMA, ""})54}55}56toks = append(toks, Token{token.RBRACK, ""})5758case value.TypeObject:59toks = append(toks, Token{token.LCURLY, ""}, Token{token.LITERAL, "\n"})6061keys := v.Keys()6263// If v isn't an ordered object (i.e., a go map), sort the keys so they64// have a deterministic print order.65if !v.OrderedKeys() {66sort.Strings(keys)67}6869for i := 0; i < len(keys); i++ {70if isValidIdentifier(keys[i]) {71toks = append(toks, Token{token.IDENT, keys[i]})72} else {73toks = append(toks, Token{token.STRING, fmt.Sprintf("%q", keys[i])})74}7576field, _ := v.Key(keys[i])77toks = append(toks, Token{token.ASSIGN, ""})78toks = append(toks, valueTokens(field)...)79toks = append(toks, Token{token.COMMA, ""}, Token{token.LITERAL, "\n"})80}81toks = append(toks, Token{token.RCURLY, ""})8283case value.TypeFunction:84toks = append(toks, Token{token.LITERAL, v.Describe()})8586case value.TypeCapsule:87toks = append(toks, Token{token.LITERAL, v.Describe()})8889default:90panic(fmt.Sprintf("river/token/builder: unrecognized value type %q", v.Type()))91}9293return toks94}9596func isValidIdentifier(in string) bool {97s := scanner.New(nil, []byte(in), nil, 0)98_, tok, lit := s.Scan()99return tok == token.IDENT && lit == in100}101102103