// Package river implements a high-level API for decoding and encoding River1// configuration files. The mapping between River and Go values is described in2// the documentation for the Unmarshal and Marshal functions.3//4// Lower-level APIs which give more control over configuration evaluation are5// available in the inner packages. The implementation of this package is6// minimal and serves as a reference for how to consume the lower-level7// packages.8package river910import (11"bytes"12"io"1314"github.com/grafana/agent/pkg/river/parser"15"github.com/grafana/agent/pkg/river/token/builder"16"github.com/grafana/agent/pkg/river/vm"17)1819// Marshal returns the pretty-printed encoding of v as a River configuration20// file. v must be a Go struct with river struct tags which determine the21// structure of the resulting file.22//23// Marshal traverses the value v recursively, encoding each struct field as a24// River block or River attribute, based on the flags provided to the river25// struct tag.26//27// When a struct field represents a River block, Marshal creates a new block28// and recursively encodes the value as the body of the block. The name of the29// created block is taken from the name specified by the river struct tag.30//31// Struct fields which represent River blocks must be either a Go struct or a32// slice of Go structs. When the field is a Go struct, its value is encoded as33// a single block. When the field is a slice of Go structs, a block is created34// for each element in the slice.35//36// When encoding a block, if the inner Go struct has a struct field37// representing a River block label, the value of that field is used as the38// label name for the created block. Fields used for River block labels must be39// the string type. When specified, there must not be more than one struct40// field which represents a block label.41//42// The river tag specifies a name, possibly followed by a comma-separated list43// of options. The name must be empty if the provided options do not support a44// name being defined. The following provides examples for all supported struct45// field tags with their meanings:46//47// // Field appears as a block named "example". It will always appear in the48// // resulting encoding. When decoding, "example" is treated as a required49// // block and must be present in the source text.50// Field struct{...} `river:"example,block"`51//52// // Field appears as a set of blocks named "example." It will appear in the53// // resulting encoding if there is at least one element in the slice. When54// // decoding, "example" is treated as a required block and at least one55// // "example" block must be present in the source text.56// Field []struct{...} `river:"example,block"`57//58// // Field appears as block named "example." It will always appear in the59// // resulting encoding. When decoding, "example" is treated as an optional60// // block and can be omitted from the source text.61// Field struct{...} `river:"example,block,optional"`62//63// // Field appears as a set of blocks named "example." It will appear in the64// // resulting encoding if there is at least one element in the slice. When65// // decoding, "example" is treated as an optional block and can be omitted66// // from the source text.67// Field []struct{...} `river:"example,block,optional"`68//69// // Field appears as an attribute named "example." It will always appear in70// // the resulting encoding. When decoding, "example" is treated as a71// // required attribute and must be present in the source text.72// Field bool `river:"example,attr"`73//74// // Field appears as an attribute named "example." If the field's value is75// // the Go zero value, "example" is omitted from the resulting encoding.76// // When decoding, "example" is treated as an optional attribute and can be77// // omitted from the source text.78// Field bool `river:"example,attr,optional"`79//80// // The value of Field appears as the block label for the struct being81// // converted into a block. When decoding, a block label must be provided.82// Field string `river:",label"`83//84// // The inner attributes and blocks of Field are exposed as top-level85// // attributes and blocks of the outer struct.86// Field struct{...} `river:",squash"`87//88// // Field appears as a set of blocks starting with "example.". Only the89// // first set element in the struct will be encoded. Each field in struct90// // must be a block. The name of the block is prepended to the enum name.91// // When decoding, enum blocks are treated as optional blocks and can be92// // omitted from the source text.93// Field []struct{...} `river:"example,enum"`94//95// // Field is equivalent to `river:"example,enum"`.96// Field []struct{...} `river:"example,enum,optional"`97//98// If a river tag specifies a required or optional block, the name is permitted99// to contain period `.` characters.100//101// Marshal will panic if it encounters a struct with invalid river tags.102//103// When a struct field represents a River attribute, Marshal encodes the struct104// value as a River value. The attribute name will be taken from the name105// specified by the river struct tag. See MarshalValue for the rules used to106// convert a Go value into a River value.107func Marshal(v interface{}) ([]byte, error) {108var buf bytes.Buffer109if err := NewEncoder(&buf).Encode(v); err != nil {110return nil, err111}112return buf.Bytes(), nil113}114115// MarshalValue returns the pretty-printed encoding of v as a River value.116//117// MarshalValue traverses the value v recursively. If an encountered value118// implements the encoding.TextMarshaler interface, MarshalValue calls its119// MarshalText method and encodes the result as a River string. If a value120// implements the Capsule interface, it always encodes as a River capsule121// value.122//123// Otherwise, MarshalValue uses the following type-dependent default encodings:124//125// Boolean values encode to River bools.126//127// Floating point, integer, and Number values encode to River numbers.128//129// String values encode to River strings.130//131// Array and slice values encode to River arrays, except that []byte is132// converted into a River string. Nil slices encode as an empty array and nil133// []byte slices encode as an empty string.134//135// Structs encode to River objects, using Go struct field tags to determine the136// resulting structure of the River object. Each exported struct field with a137// river tag becomes an object field, using the tag name as the field name.138// Other struct fields are ignored. If no struct field has a river tag, the139// struct encodes to a River capsule instead.140//141// Function values encode to River functions, which appear in the resulting142// text as strings formatted as "function(GO_TYPE)".143//144// All other Go values encode to River capsules, which appear in the resulting145// text as strings formatted as "capsule(GO_TYPE)".146//147// The river tag specifies the field name, possibly followed by a148// comma-separated list of options. The following provides examples for all149// supported struct field tags with their meanings:150//151// // Field appears as an object field named "my_name". It will always152// // appear in the resulting encoding. When decoding, "my_name" is treated153// // as a required attribute and must be present in the source text.154// Field bool `river:"my_name,attr"`155//156// // Field appears as an object field named "my_name". If the field's value157// // is the Go zero value, "example" is omitted from the resulting encoding.158// // When decoding, "my_name" is treated as an optional attribute and can be159// // omitted from the source text.160// Field bool `river:"my_name,attr,optional"`161func MarshalValue(v interface{}) ([]byte, error) {162var buf bytes.Buffer163if err := NewEncoder(&buf).EncodeValue(v); err != nil {164return nil, err165}166return buf.Bytes(), nil167}168169// Encoder writes River configuration to an output stream. Call NewEncoder to170// create instances of Encoder.171type Encoder struct {172w io.Writer173}174175// NewEncoder returns a new Encoder which writes configuration to w.176func NewEncoder(w io.Writer) *Encoder {177return &Encoder{w: w}178}179180// Encode converts the value pointed to by v into a River configuration file181// and writes the result to the Decoder's output stream.182//183// See the documentation for Marshal for details about the conversion of Go184// values into River configuration.185func (enc *Encoder) Encode(v interface{}) error {186f := builder.NewFile()187f.Body().AppendFrom(v)188189_, err := f.WriteTo(enc.w)190return err191}192193// EncodeValue converts the value pointed to by v into a River value and writes194// the result to the Decoder's output stream.195//196// See the documentation for MarshalValue for details about the conversion of197// Go values into River values.198func (enc *Encoder) EncodeValue(v interface{}) error {199expr := builder.NewExpr()200expr.SetValue(v)201202_, err := expr.WriteTo(enc.w)203return err204}205206// Unmarshal converts the River configuration file specified by in and stores207// it in the struct value pointed to by v. If v is nil or not a pointer,208// Unmarshal panics. The configuration specified by in may use expressions to209// compute values while unmarshaling. Refer to the River language documentation210// for the list of valid formatting and expression rules.211//212// Unmarshal uses the inverse of the encoding rules that Marshal uses,213// allocating maps, slices, and pointers as necessary.214//215// To unmarshal a River body into a map[string]T, Unmarshal assigns each216// attribute to a key in the map, and decodes the attribute's value as the217// value for the map entry. Only attribute statements are allowed when218// unmarshaling into a map.219//220// To unmarshal a River body into a struct, Unmarshal matches incoming221// attributes and blocks to the river struct tags specified by v. Incoming222// attribute and blocks which do not match to a river struct tag cause a223// decoding error. Additionally, any attribute or block marked as required by224// the river struct tag that are not present in the source text will generate a225// decoding error.226//227// To unmarshal a list of River blocks into a slice, Unmarshal resets the slice228// length to zero and then appends each element to the slice.229//230// To unmarshal a list of River blocks into a Go array, Unmarshal decodes each231// block into the corresponding Go array element. If the number of River blocks232// does not match the length of the Go array, a decoding error is returned.233//234// Unmarshal follows the rules specified by UnmarshalValue when unmarshaling235// the value of an attribute.236func Unmarshal(in []byte, v interface{}) error {237dec := NewDecoder(bytes.NewReader(in))238return dec.Decode(v)239}240241// UnmarshalValue converts the River configuration file specified by in and242// stores it in the value pointed to by v. If v is nil or not a pointer,243// UnmarshalValue panics. The configuration specified by in may use expressions244// to compute values while unmarshaling. Refer to the River language245// documentation for the list of valid formatting and expression rules.246//247// Unmarshal uses the inverse of the encoding rules that MarshalValue uses,248// allocating maps, slices, and pointers as necessary, with the following249// additional rules:250//251// After converting a River value into its Go value counterpart, the Go value252// may be converted into a capsule if the capsule type implements253// ConvertibleIntoCapsule.254//255// To unmarshal a River object into a struct, UnmarshalValue matches incoming256// object fields to the river struct tags specified by v. Incoming object257// fields which do not match to a river struct tag cause a decoding error.258// Additionally, any object field marked as required by the river struct259// tag that are not present in the source text will generate a decoding error.260//261// To unmarshal River into an interface value, Unmarshal stores one of the262// following:263//264// - bool, for River bools265// - float64, for River numbers266// - string, for River strings267// - []interface{}, for River arrays268// - map[string]interface{}, for River objects269//270// Capsule and function types will retain their original type when decoding271// into an interface value.272//273// To unmarshal a River array into a slice, Unmarshal resets the slice length274// to zero and then appends each element to the slice.275//276// To unmarshal a River array into a Go array, Unmarshal decodes River array277// elements into the corresponding Go array element. If the number of River278// elements does not match the length of the Go array, a decoding error is279// returned.280//281// To unmarshal a River object into a Map, Unmarshal establishes a map to use.282// If the map is nil, Unmarshal allocates a new map. Otherwise, Unmarshal283// reuses the existing map, keeping existing entries. Unmarshal then stores284// key-value pairs from the River object into the map. The map's key type must285// be string.286func UnmarshalValue(in []byte, v interface{}) error {287dec := NewDecoder(bytes.NewReader(in))288return dec.DecodeValue(v)289}290291// Decoder reads River configuration from an input stream. Call NewDecoder to292// create instances of Decoder.293type Decoder struct {294r io.Reader295}296297// NewDecoder returns a new Decoder which reads configuration from r.298func NewDecoder(r io.Reader) *Decoder {299return &Decoder{r: r}300}301302// Decode reads the River-encoded file from the Decoder's input and stores it303// in the value pointed to by v. Data will be read from the Decoder's input304// until EOF is reached.305//306// See the documentation for Unmarshal for details about the conversion of River307// configuration into Go values.308func (dec *Decoder) Decode(v interface{}) error {309bb, err := io.ReadAll(dec.r)310if err != nil {311return err312}313314f, err := parser.ParseFile("", bb)315if err != nil {316return err317}318319eval := vm.New(f)320return eval.Evaluate(nil, v)321}322323// DecodeValue reads the River-encoded expression from the Decoder's input and324// stores it in the value pointed to by v. Data will be read from the Decoder's325// input until EOF is reached.326//327// See the documentation for UnmarshalValue for details about the conversion of328// River values into Go values.329func (dec *Decoder) DecodeValue(v interface{}) error {330bb, err := io.ReadAll(dec.r)331if err != nil {332return err333}334335f, err := parser.ParseExpression(string(bb))336if err != nil {337return err338}339340eval := vm.New(f)341return eval.Evaluate(nil, v)342}343344345