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 }