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