1// Package el implements expression language "GoEL". 2// 3// The API is error-free by design. Malformed expressions simply have no result. 4// 5// Slash-separated paths specify content for lookups or modification. All paths 6// are subjected to normalization rules. See http://golang.org/pkg/path#Clean 7// 8// path ::= path-component | path path-component 9// path-component ::= "/" segment 10// segment ::= "" | ".." | selection | selection key 11// selection ::= "." | go-field-name 12// key ::= "[" key-selection "]" 13// key-selection ::= "*" | go-literal 14// 15// Both exported and non-exported struct fields can be selected by name. 16// 17// Elements in indexed types array, slice and string are denoted with a zero 18// based number inbetween square brackets. Key selections from map types also 19// use the square bracket notation. Asterisk is treated as a wildcard. 20package el 21 22import ( 23 "reflect" 24) 25 26// finisher deals with post modification requirements. 27type finisher interface { 28 Finish() 29} 30 31func eval(expr string, root interface{}, buildCallbacks *[]finisher) []reflect.Value { 32 if expr == "" { 33 return nil 34 } 35 36 switch expr[0] { 37 case '/': 38 return resolve(expr, root, buildCallbacks) 39 default: 40 return nil 41 } 42} 43 44// Assign applies want to the path on root and returns the number of successes. 45// 46// All content in the path is instantiated the fly with the zero value where 47// possible. This implies automatic construction of structs, pointers and maps. 48// 49// For the operation to succeed the targets must be settable conform to the 50// third law of reflection. 51// In short, root should be a pointer and the destination should be exported. 52// See http://blog.golang.org/laws-of-reflection#TOC_8%2E 53func Assign(root interface{}, path string, want interface{}) (n int) { 54 var buildCallbacks []finisher 55 56 values := eval(path, root, &buildCallbacks) 57 58 w := follow(reflect.ValueOf(want), false) 59 if !w.IsValid() { 60 return 61 } 62 wt := w.Type() 63 64 for _, v := range values { 65 if !v.CanSet() { 66 continue 67 } 68 69 switch vt := v.Type(); { 70 case wt.AssignableTo(vt): 71 v.Set(w) 72 n++ 73 case wt.ConvertibleTo(vt): 74 v.Set(w.Convert(vt)) 75 n++ 76 } 77 } 78 79 for _, c := range buildCallbacks { 80 c.Finish() 81 } 82 83 return n 84} 85 86// Bool returns the evaluation result if, and only if, the result has one value 87// and the value is a boolean type. 88func Bool(expr string, root interface{}) (result bool, ok bool) { 89 a := eval(expr, root, nil) 90 if len(a) == 1 { 91 v := a[0] 92 if v.Kind() == reflect.Bool { 93 return v.Bool(), true 94 } 95 } 96 return 97} 98 99// Int returns the evaluation result if, and only if, the result has one value 100// and the value is an integer type. 101func Int(expr string, root interface{}) (result int64, ok bool) { 102 a := eval(expr, root, nil) 103 if len(a) == 1 { 104 v := a[0] 105 switch v.Kind() { 106 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 107 return v.Int(), true 108 } 109 } 110 return 111} 112 113// Uint returns the evaluation result if, and only if, the result has one value 114// and the value is an unsigned integer type. 115func Uint(expr string, root interface{}) (result uint64, ok bool) { 116 a := eval(expr, root, nil) 117 if len(a) == 1 { 118 v := a[0] 119 switch v.Kind() { 120 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 121 return v.Uint(), true 122 } 123 } 124 return 125} 126 127// Float returns the evaluation result if, and only if, the result has one value 128// and the value is a floating point type. 129func Float(expr string, root interface{}) (result float64, ok bool) { 130 a := eval(expr, root, nil) 131 if len(a) == 1 { 132 v := a[0] 133 switch v.Kind() { 134 case reflect.Float32, reflect.Float64: 135 return v.Float(), true 136 } 137 } 138 return 139} 140 141// Complex returns the evaluation result if, and only if, the result has one 142// value and the value is a complex type. 143func Complex(expr string, root interface{}) (result complex128, ok bool) { 144 a := eval(expr, root, nil) 145 if len(a) == 1 { 146 v := a[0] 147 switch v.Kind() { 148 case reflect.Complex64, reflect.Complex128: 149 return v.Complex(), true 150 } 151 } 152 return 153} 154 155// String returns the evaluation result if, and only if, the result has one 156// value and the value is a string type. 157func String(expr string, root interface{}) (result string, ok bool) { 158 a := eval(expr, root, nil) 159 if len(a) == 1 { 160 v := a[0] 161 if v.Kind() == reflect.String { 162 return v.String(), true 163 } 164 } 165 return 166} 167 168// Any returns the evaluation result values. 169func Any(expr string, root interface{}) []interface{} { 170 a := eval(expr, root, nil) 171 if len(a) == 0 { 172 return nil 173 } 174 175 b := make([]interface{}, 0, len(a)) 176 for _, v := range a { 177 if x := asInterface(v); x != nil { 178 b = append(b, x) 179 } 180 } 181 return b 182} 183 184// Bools returns the evaluation result values of a boolean type. 185func Bools(expr string, root interface{}) []bool { 186 a := eval(expr, root, nil) 187 if len(a) == 0 { 188 return nil 189 } 190 191 b := make([]bool, 0, len(a)) 192 for _, v := range a { 193 if v.Kind() == reflect.Bool { 194 b = append(b, v.Bool()) 195 } 196 } 197 return b 198} 199 200// Ints returns the evaluation result values of an integer type. 201func Ints(expr string, root interface{}) []int64 { 202 a := eval(expr, root, nil) 203 if len(a) == 0 { 204 return nil 205 } 206 207 b := make([]int64, 0, len(a)) 208 for _, v := range a { 209 switch v.Kind() { 210 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 211 b = append(b, v.Int()) 212 } 213 } 214 return b 215} 216 217// Uints returns the evaluation result values of an unsigned integer type. 218func Uints(expr string, root interface{}) []uint64 { 219 a := eval(expr, root, nil) 220 if len(a) == 0 { 221 return nil 222 } 223 224 b := make([]uint64, 0, len(a)) 225 for _, v := range a { 226 switch v.Kind() { 227 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 228 b = append(b, v.Uint()) 229 } 230 } 231 return b 232} 233 234// Floats returns the evaluation result values of a floating point type. 235func Floats(expr string, root interface{}) []float64 { 236 a := eval(expr, root, nil) 237 if len(a) == 0 { 238 return nil 239 } 240 241 b := make([]float64, 0, len(a)) 242 for _, v := range a { 243 switch v.Kind() { 244 case reflect.Float32, reflect.Float64: 245 b = append(b, v.Float()) 246 } 247 } 248 return b 249} 250 251// Complexes returns the evaluation result values of a complex type. 252func Complexes(expr string, root interface{}) []complex128 { 253 a := eval(expr, root, nil) 254 if len(a) == 0 { 255 return nil 256 } 257 258 b := make([]complex128, 0, len(a)) 259 for _, v := range a { 260 switch v.Kind() { 261 case reflect.Complex64, reflect.Complex128: 262 b = append(b, v.Complex()) 263 } 264 } 265 return b 266} 267 268// Strings returns the evaluation result values of a string type. 269func Strings(expr string, root interface{}) []string { 270 a := eval(expr, root, nil) 271 if len(a) == 0 { 272 return nil 273 } 274 275 b := make([]string, 0, len(a)) 276 for _, v := range a { 277 if v.Kind() == reflect.String { 278 b = append(b, v.String()) 279 } 280 } 281 return b 282} 283 284func asInterface(v reflect.Value) interface{} { 285 switch v.Kind() { 286 case reflect.Invalid: 287 return nil 288 case reflect.Bool: 289 return v.Bool() 290 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 291 return v.Int() 292 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 293 return v.Uint() 294 case reflect.Float32, reflect.Float64: 295 return v.Float() 296 case reflect.Complex64, reflect.Complex128: 297 return v.Complex() 298 case reflect.String: 299 return v.String() 300 default: 301 if v.CanInterface() { 302 return v.Interface() 303 } 304 return nil 305 } 306} 307