github.com/aavshr/aws-sdk-go@v1.41.3/internal/ini/visitor.go (about)

     1  package ini
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  )
     7  
     8  // Visitor is an interface used by walkers that will
     9  // traverse an array of ASTs.
    10  type Visitor interface {
    11  	VisitExpr(AST) error
    12  	VisitStatement(AST) error
    13  }
    14  
    15  // DefaultVisitor is used to visit statements and expressions
    16  // and ensure that they are both of the correct format.
    17  // In addition, upon visiting this will build sections and populate
    18  // the Sections field which can be used to retrieve profile
    19  // configuration.
    20  type DefaultVisitor struct {
    21  	scope    string
    22  	Sections Sections
    23  }
    24  
    25  // NewDefaultVisitor return a DefaultVisitor
    26  func NewDefaultVisitor() *DefaultVisitor {
    27  	return &DefaultVisitor{
    28  		Sections: Sections{
    29  			container: map[string]Section{},
    30  		},
    31  	}
    32  }
    33  
    34  // VisitExpr visits expressions...
    35  func (v *DefaultVisitor) VisitExpr(expr AST) error {
    36  	t := v.Sections.container[v.scope]
    37  	if t.values == nil {
    38  		t.values = values{}
    39  	}
    40  
    41  	switch expr.Kind {
    42  	case ASTKindExprStatement:
    43  		opExpr := expr.GetRoot()
    44  		switch opExpr.Kind {
    45  		case ASTKindEqualExpr:
    46  			children := opExpr.GetChildren()
    47  			if len(children) <= 1 {
    48  				return NewParseError("unexpected token type")
    49  			}
    50  
    51  			rhs := children[1]
    52  
    53  			// The right-hand value side the equality expression is allowed to contain '[', ']', ':', '=' in the values.
    54  			// If the token is not either a literal or one of the token types that identifies those four additional
    55  			// tokens then error.
    56  			if !(rhs.Root.Type() == TokenLit || rhs.Root.Type() == TokenOp || rhs.Root.Type() == TokenSep) {
    57  				return NewParseError("unexpected token type")
    58  			}
    59  
    60  			key := EqualExprKey(opExpr)
    61  			v, err := newValue(rhs.Root.ValueType, rhs.Root.base, rhs.Root.Raw())
    62  			if err != nil {
    63  				return err
    64  			}
    65  
    66  			t.values[key] = v
    67  		default:
    68  			return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
    69  		}
    70  	default:
    71  		return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
    72  	}
    73  
    74  	v.Sections.container[v.scope] = t
    75  	return nil
    76  }
    77  
    78  // VisitStatement visits statements...
    79  func (v *DefaultVisitor) VisitStatement(stmt AST) error {
    80  	switch stmt.Kind {
    81  	case ASTKindCompletedSectionStatement:
    82  		child := stmt.GetRoot()
    83  		if child.Kind != ASTKindSectionStatement {
    84  			return NewParseError(fmt.Sprintf("unsupported child statement: %T", child))
    85  		}
    86  
    87  		name := string(child.Root.Raw())
    88  		v.Sections.container[name] = Section{}
    89  		v.scope = name
    90  	default:
    91  		return NewParseError(fmt.Sprintf("unsupported statement: %s", stmt.Kind))
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  // Sections is a map of Section structures that represent
    98  // a configuration.
    99  type Sections struct {
   100  	container map[string]Section
   101  }
   102  
   103  // GetSection will return section p. If section p does not exist,
   104  // false will be returned in the second parameter.
   105  func (t Sections) GetSection(p string) (Section, bool) {
   106  	v, ok := t.container[p]
   107  	return v, ok
   108  }
   109  
   110  // values represents a map of union values.
   111  type values map[string]Value
   112  
   113  // List will return a list of all sections that were successfully
   114  // parsed.
   115  func (t Sections) List() []string {
   116  	keys := make([]string, len(t.container))
   117  	i := 0
   118  	for k := range t.container {
   119  		keys[i] = k
   120  		i++
   121  	}
   122  
   123  	sort.Strings(keys)
   124  	return keys
   125  }
   126  
   127  // Section contains a name and values. This represent
   128  // a sectioned entry in a configuration file.
   129  type Section struct {
   130  	Name   string
   131  	values values
   132  }
   133  
   134  // Has will return whether or not an entry exists in a given section
   135  func (t Section) Has(k string) bool {
   136  	_, ok := t.values[k]
   137  	return ok
   138  }
   139  
   140  // ValueType will returned what type the union is set to. If
   141  // k was not found, the NoneType will be returned.
   142  func (t Section) ValueType(k string) (ValueType, bool) {
   143  	v, ok := t.values[k]
   144  	return v.Type, ok
   145  }
   146  
   147  // Bool returns a bool value at k
   148  func (t Section) Bool(k string) bool {
   149  	return t.values[k].BoolValue()
   150  }
   151  
   152  // Int returns an integer value at k
   153  func (t Section) Int(k string) int64 {
   154  	return t.values[k].IntValue()
   155  }
   156  
   157  // Float64 returns a float value at k
   158  func (t Section) Float64(k string) float64 {
   159  	return t.values[k].FloatValue()
   160  }
   161  
   162  // String returns the string value at k
   163  func (t Section) String(k string) string {
   164  	_, ok := t.values[k]
   165  	if !ok {
   166  		return ""
   167  	}
   168  	return t.values[k].StringValue()
   169  }