Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/river/river.go
4094 views
1
// Package river implements a high-level API for decoding and encoding River
2
// configuration files. The mapping between River and Go values is described in
3
// the documentation for the Unmarshal and Marshal functions.
4
//
5
// Lower-level APIs which give more control over configuration evaluation are
6
// available in the inner packages. The implementation of this package is
7
// minimal and serves as a reference for how to consume the lower-level
8
// packages.
9
package river
10
11
import (
12
"bytes"
13
"io"
14
15
"github.com/grafana/agent/pkg/river/parser"
16
"github.com/grafana/agent/pkg/river/token/builder"
17
"github.com/grafana/agent/pkg/river/vm"
18
)
19
20
// Marshal returns the pretty-printed encoding of v as a River configuration
21
// file. v must be a Go struct with river struct tags which determine the
22
// structure of the resulting file.
23
//
24
// Marshal traverses the value v recursively, encoding each struct field as a
25
// River block or River attribute, based on the flags provided to the river
26
// struct tag.
27
//
28
// When a struct field represents a River block, Marshal creates a new block
29
// and recursively encodes the value as the body of the block. The name of the
30
// created block is taken from the name specified by the river struct tag.
31
//
32
// Struct fields which represent River blocks must be either a Go struct or a
33
// slice of Go structs. When the field is a Go struct, its value is encoded as
34
// a single block. When the field is a slice of Go structs, a block is created
35
// for each element in the slice.
36
//
37
// When encoding a block, if the inner Go struct has a struct field
38
// representing a River block label, the value of that field is used as the
39
// label name for the created block. Fields used for River block labels must be
40
// the string type. When specified, there must not be more than one struct
41
// field which represents a block label.
42
//
43
// The river tag specifies a name, possibly followed by a comma-separated list
44
// of options. The name must be empty if the provided options do not support a
45
// name being defined. The following provides examples for all supported struct
46
// field tags with their meanings:
47
//
48
// // Field appears as a block named "example". It will always appear in the
49
// // resulting encoding. When decoding, "example" is treated as a required
50
// // block and must be present in the source text.
51
// Field struct{...} `river:"example,block"`
52
//
53
// // Field appears as a set of blocks named "example." It will appear in the
54
// // resulting encoding if there is at least one element in the slice. When
55
// // decoding, "example" is treated as a required block and at least one
56
// // "example" block must be present in the source text.
57
// Field []struct{...} `river:"example,block"`
58
//
59
// // Field appears as block named "example." It will always appear in the
60
// // resulting encoding. When decoding, "example" is treated as an optional
61
// // block and can be omitted from the source text.
62
// Field struct{...} `river:"example,block,optional"`
63
//
64
// // Field appears as a set of blocks named "example." It will appear in the
65
// // resulting encoding if there is at least one element in the slice. When
66
// // decoding, "example" is treated as an optional block and can be omitted
67
// // from the source text.
68
// Field []struct{...} `river:"example,block,optional"`
69
//
70
// // Field appears as an attribute named "example." It will always appear in
71
// // the resulting encoding. When decoding, "example" is treated as a
72
// // required attribute and must be present in the source text.
73
// Field bool `river:"example,attr"`
74
//
75
// // Field appears as an attribute named "example." If the field's value is
76
// // the Go zero value, "example" is omitted from the resulting encoding.
77
// // When decoding, "example" is treated as an optional attribute and can be
78
// // omitted from the source text.
79
// Field bool `river:"example,attr,optional"`
80
//
81
// // The value of Field appears as the block label for the struct being
82
// // converted into a block. When decoding, a block label must be provided.
83
// Field string `river:",label"`
84
//
85
// // The inner attributes and blocks of Field are exposed as top-level
86
// // attributes and blocks of the outer struct.
87
// Field struct{...} `river:",squash"`
88
//
89
// // Field appears as a set of blocks starting with "example.". Only the
90
// // first set element in the struct will be encoded. Each field in struct
91
// // must be a block. The name of the block is prepended to the enum name.
92
// // When decoding, enum blocks are treated as optional blocks and can be
93
// // omitted from the source text.
94
// Field []struct{...} `river:"example,enum"`
95
//
96
// // Field is equivalent to `river:"example,enum"`.
97
// Field []struct{...} `river:"example,enum,optional"`
98
//
99
// If a river tag specifies a required or optional block, the name is permitted
100
// to contain period `.` characters.
101
//
102
// Marshal will panic if it encounters a struct with invalid river tags.
103
//
104
// When a struct field represents a River attribute, Marshal encodes the struct
105
// value as a River value. The attribute name will be taken from the name
106
// specified by the river struct tag. See MarshalValue for the rules used to
107
// convert a Go value into a River value.
108
func Marshal(v interface{}) ([]byte, error) {
109
var buf bytes.Buffer
110
if err := NewEncoder(&buf).Encode(v); err != nil {
111
return nil, err
112
}
113
return buf.Bytes(), nil
114
}
115
116
// MarshalValue returns the pretty-printed encoding of v as a River value.
117
//
118
// MarshalValue traverses the value v recursively. If an encountered value
119
// implements the encoding.TextMarshaler interface, MarshalValue calls its
120
// MarshalText method and encodes the result as a River string. If a value
121
// implements the Capsule interface, it always encodes as a River capsule
122
// value.
123
//
124
// Otherwise, MarshalValue uses the following type-dependent default encodings:
125
//
126
// Boolean values encode to River bools.
127
//
128
// Floating point, integer, and Number values encode to River numbers.
129
//
130
// String values encode to River strings.
131
//
132
// Array and slice values encode to River arrays, except that []byte is
133
// converted into a River string. Nil slices encode as an empty array and nil
134
// []byte slices encode as an empty string.
135
//
136
// Structs encode to River objects, using Go struct field tags to determine the
137
// resulting structure of the River object. Each exported struct field with a
138
// river tag becomes an object field, using the tag name as the field name.
139
// Other struct fields are ignored. If no struct field has a river tag, the
140
// struct encodes to a River capsule instead.
141
//
142
// Function values encode to River functions, which appear in the resulting
143
// text as strings formatted as "function(GO_TYPE)".
144
//
145
// All other Go values encode to River capsules, which appear in the resulting
146
// text as strings formatted as "capsule(GO_TYPE)".
147
//
148
// The river tag specifies the field name, possibly followed by a
149
// comma-separated list of options. The following provides examples for all
150
// supported struct field tags with their meanings:
151
//
152
// // Field appears as an object field named "my_name". It will always
153
// // appear in the resulting encoding. When decoding, "my_name" is treated
154
// // as a required attribute and must be present in the source text.
155
// Field bool `river:"my_name,attr"`
156
//
157
// // Field appears as an object field named "my_name". If the field's value
158
// // is the Go zero value, "example" is omitted from the resulting encoding.
159
// // When decoding, "my_name" is treated as an optional attribute and can be
160
// // omitted from the source text.
161
// Field bool `river:"my_name,attr,optional"`
162
func MarshalValue(v interface{}) ([]byte, error) {
163
var buf bytes.Buffer
164
if err := NewEncoder(&buf).EncodeValue(v); err != nil {
165
return nil, err
166
}
167
return buf.Bytes(), nil
168
}
169
170
// Encoder writes River configuration to an output stream. Call NewEncoder to
171
// create instances of Encoder.
172
type Encoder struct {
173
w io.Writer
174
}
175
176
// NewEncoder returns a new Encoder which writes configuration to w.
177
func NewEncoder(w io.Writer) *Encoder {
178
return &Encoder{w: w}
179
}
180
181
// Encode converts the value pointed to by v into a River configuration file
182
// and writes the result to the Decoder's output stream.
183
//
184
// See the documentation for Marshal for details about the conversion of Go
185
// values into River configuration.
186
func (enc *Encoder) Encode(v interface{}) error {
187
f := builder.NewFile()
188
f.Body().AppendFrom(v)
189
190
_, err := f.WriteTo(enc.w)
191
return err
192
}
193
194
// EncodeValue converts the value pointed to by v into a River value and writes
195
// the result to the Decoder's output stream.
196
//
197
// See the documentation for MarshalValue for details about the conversion of
198
// Go values into River values.
199
func (enc *Encoder) EncodeValue(v interface{}) error {
200
expr := builder.NewExpr()
201
expr.SetValue(v)
202
203
_, err := expr.WriteTo(enc.w)
204
return err
205
}
206
207
// Unmarshal converts the River configuration file specified by in and stores
208
// it in the struct value pointed to by v. If v is nil or not a pointer,
209
// Unmarshal panics. The configuration specified by in may use expressions to
210
// compute values while unmarshaling. Refer to the River language documentation
211
// for the list of valid formatting and expression rules.
212
//
213
// Unmarshal uses the inverse of the encoding rules that Marshal uses,
214
// allocating maps, slices, and pointers as necessary.
215
//
216
// To unmarshal a River body into a map[string]T, Unmarshal assigns each
217
// attribute to a key in the map, and decodes the attribute's value as the
218
// value for the map entry. Only attribute statements are allowed when
219
// unmarshaling into a map.
220
//
221
// To unmarshal a River body into a struct, Unmarshal matches incoming
222
// attributes and blocks to the river struct tags specified by v. Incoming
223
// attribute and blocks which do not match to a river struct tag cause a
224
// decoding error. Additionally, any attribute or block marked as required by
225
// the river struct tag that are not present in the source text will generate a
226
// decoding error.
227
//
228
// To unmarshal a list of River blocks into a slice, Unmarshal resets the slice
229
// length to zero and then appends each element to the slice.
230
//
231
// To unmarshal a list of River blocks into a Go array, Unmarshal decodes each
232
// block into the corresponding Go array element. If the number of River blocks
233
// does not match the length of the Go array, a decoding error is returned.
234
//
235
// Unmarshal follows the rules specified by UnmarshalValue when unmarshaling
236
// the value of an attribute.
237
func Unmarshal(in []byte, v interface{}) error {
238
dec := NewDecoder(bytes.NewReader(in))
239
return dec.Decode(v)
240
}
241
242
// UnmarshalValue converts the River configuration file specified by in and
243
// stores it in the value pointed to by v. If v is nil or not a pointer,
244
// UnmarshalValue panics. The configuration specified by in may use expressions
245
// to compute values while unmarshaling. Refer to the River language
246
// documentation for the list of valid formatting and expression rules.
247
//
248
// Unmarshal uses the inverse of the encoding rules that MarshalValue uses,
249
// allocating maps, slices, and pointers as necessary, with the following
250
// additional rules:
251
//
252
// After converting a River value into its Go value counterpart, the Go value
253
// may be converted into a capsule if the capsule type implements
254
// ConvertibleIntoCapsule.
255
//
256
// To unmarshal a River object into a struct, UnmarshalValue matches incoming
257
// object fields to the river struct tags specified by v. Incoming object
258
// fields which do not match to a river struct tag cause a decoding error.
259
// Additionally, any object field marked as required by the river struct
260
// tag that are not present in the source text will generate a decoding error.
261
//
262
// To unmarshal River into an interface value, Unmarshal stores one of the
263
// following:
264
//
265
// - bool, for River bools
266
// - float64, for River numbers
267
// - string, for River strings
268
// - []interface{}, for River arrays
269
// - map[string]interface{}, for River objects
270
//
271
// Capsule and function types will retain their original type when decoding
272
// into an interface value.
273
//
274
// To unmarshal a River array into a slice, Unmarshal resets the slice length
275
// to zero and then appends each element to the slice.
276
//
277
// To unmarshal a River array into a Go array, Unmarshal decodes River array
278
// elements into the corresponding Go array element. If the number of River
279
// elements does not match the length of the Go array, a decoding error is
280
// returned.
281
//
282
// To unmarshal a River object into a Map, Unmarshal establishes a map to use.
283
// If the map is nil, Unmarshal allocates a new map. Otherwise, Unmarshal
284
// reuses the existing map, keeping existing entries. Unmarshal then stores
285
// key-value pairs from the River object into the map. The map's key type must
286
// be string.
287
func UnmarshalValue(in []byte, v interface{}) error {
288
dec := NewDecoder(bytes.NewReader(in))
289
return dec.DecodeValue(v)
290
}
291
292
// Decoder reads River configuration from an input stream. Call NewDecoder to
293
// create instances of Decoder.
294
type Decoder struct {
295
r io.Reader
296
}
297
298
// NewDecoder returns a new Decoder which reads configuration from r.
299
func NewDecoder(r io.Reader) *Decoder {
300
return &Decoder{r: r}
301
}
302
303
// Decode reads the River-encoded file from the Decoder's input and stores it
304
// in the value pointed to by v. Data will be read from the Decoder's input
305
// until EOF is reached.
306
//
307
// See the documentation for Unmarshal for details about the conversion of River
308
// configuration into Go values.
309
func (dec *Decoder) Decode(v interface{}) error {
310
bb, err := io.ReadAll(dec.r)
311
if err != nil {
312
return err
313
}
314
315
f, err := parser.ParseFile("", bb)
316
if err != nil {
317
return err
318
}
319
320
eval := vm.New(f)
321
return eval.Evaluate(nil, v)
322
}
323
324
// DecodeValue reads the River-encoded expression from the Decoder's input and
325
// stores it in the value pointed to by v. Data will be read from the Decoder's
326
// input until EOF is reached.
327
//
328
// See the documentation for UnmarshalValue for details about the conversion of
329
// River values into Go values.
330
func (dec *Decoder) DecodeValue(v interface{}) error {
331
bb, err := io.ReadAll(dec.r)
332
if err != nil {
333
return err
334
}
335
336
f, err := parser.ParseExpression(string(bb))
337
if err != nil {
338
return err
339
}
340
341
eval := vm.New(f)
342
return eval.Evaluate(nil, v)
343
}
344
345