| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package config
- import (
- "encoding/json"
- "errors"
- "fmt"
- "slices"
- "strings"
- )
- var (
- ErrExpressionOrListMustBeStringOrObject = errors.New("config: this must be a string or an object")
- ErrExpressionEmpty = errors.New("config: this expression is empty")
- ErrExpressionCantHaveBoth = errors.New("config: expression block can't contain multiple expression types")
- )
- type ExpressionOrList struct {
- Expression string `json:"-" yaml:"-"`
- All []string `json:"all,omitempty" yaml:"all,omitempty"`
- Any []string `json:"any,omitempty" yaml:"any,omitempty"`
- }
- func (eol ExpressionOrList) String() string {
- switch {
- case len(eol.Expression) != 0:
- return eol.Expression
- case len(eol.All) != 0:
- var sb strings.Builder
- for i, pred := range eol.All {
- if i != 0 {
- fmt.Fprintf(&sb, " && ")
- }
- fmt.Fprintf(&sb, "( %s )", pred)
- }
- return sb.String()
- case len(eol.Any) != 0:
- var sb strings.Builder
- for i, pred := range eol.Any {
- if i != 0 {
- fmt.Fprintf(&sb, " || ")
- }
- fmt.Fprintf(&sb, "( %s )", pred)
- }
- return sb.String()
- }
- panic("this should not happen")
- }
- func (eol ExpressionOrList) Equal(rhs *ExpressionOrList) bool {
- if eol.Expression != rhs.Expression {
- return false
- }
- if !slices.Equal(eol.All, rhs.All) {
- return false
- }
- if !slices.Equal(eol.Any, rhs.Any) {
- return false
- }
- return true
- }
- func (eol *ExpressionOrList) MarshalYAML() (any, error) {
- switch {
- case len(eol.All) == 1 && len(eol.Any) == 0:
- eol.Expression = eol.All[0]
- eol.All = nil
- case len(eol.Any) == 1 && len(eol.All) == 0:
- eol.Expression = eol.Any[0]
- eol.Any = nil
- }
- if eol.Expression != "" {
- return eol.Expression, nil
- }
- type RawExpressionOrList ExpressionOrList
- return RawExpressionOrList(*eol), nil
- }
- func (eol *ExpressionOrList) MarshalJSON() ([]byte, error) {
- switch {
- case len(eol.All) == 1 && len(eol.Any) == 0:
- eol.Expression = eol.All[0]
- eol.All = nil
- case len(eol.Any) == 1 && len(eol.All) == 0:
- eol.Expression = eol.Any[0]
- eol.Any = nil
- }
- if eol.Expression != "" {
- return json.Marshal(string(eol.Expression))
- }
- type RawExpressionOrList ExpressionOrList
- val := RawExpressionOrList(*eol)
- return json.Marshal(val)
- }
- func (eol *ExpressionOrList) UnmarshalJSON(data []byte) error {
- switch string(data[0]) {
- case `"`: // string
- return json.Unmarshal(data, &eol.Expression)
- case "{": // object
- type RawExpressionOrList ExpressionOrList
- var val RawExpressionOrList
- if err := json.Unmarshal(data, &val); err != nil {
- return err
- }
- eol.All = val.All
- eol.Any = val.Any
- return nil
- }
- return ErrExpressionOrListMustBeStringOrObject
- }
- func (eol *ExpressionOrList) Valid() error {
- if eol.Expression == "" && len(eol.All) == 0 && len(eol.Any) == 0 {
- return ErrExpressionEmpty
- }
- if len(eol.All) != 0 && len(eol.Any) != 0 {
- return ErrExpressionCantHaveBoth
- }
- return nil
- }
|