1// Copyright © 2014 Steve Francia <spf@spf13.com>.
2//
3// Use of this source code is governed by an MIT-style
4// license that can be found in the LICENSE file.
5
6package cast
7
8import (
9	"fmt"
10	"html/template"
11	"reflect"
12	"strconv"
13	"strings"
14	"time"
15)
16
17// ToTimeE casts an empty interface to time.Time.
18func ToTimeE(i interface{}) (tim time.Time, err error) {
19	i = indirect(i)
20
21	switch v := i.(type) {
22	case time.Time:
23		return v, nil
24	case string:
25		d, e := StringToDate(v)
26		if e == nil {
27			return d, nil
28		}
29		return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e)
30	case int:
31		return time.Unix(int64(v), 0), nil
32	case int32:
33		return time.Unix(int64(v), 0), nil
34	case int64:
35		return time.Unix(v, 0), nil
36	default:
37		return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i)
38	}
39}
40
41// ToDurationE casts an empty interface to time.Duration.
42func ToDurationE(i interface{}) (d time.Duration, err error) {
43	i = indirect(i)
44
45	switch s := i.(type) {
46	case time.Duration:
47		return s, nil
48	case int64, int32, int16, int8, int:
49		d = time.Duration(ToInt64(s))
50		return
51	case float32, float64:
52		d = time.Duration(ToFloat64(s))
53		return
54	case string:
55		if strings.ContainsAny(s, "nsuµmh") {
56			d, err = time.ParseDuration(s)
57		} else {
58			d, err = time.ParseDuration(s + "ns")
59		}
60		return
61	default:
62		err = fmt.Errorf("Unable to Cast %#v to Duration\n", i)
63		return
64	}
65}
66
67// ToBoolE casts an empty interface to a bool.
68func ToBoolE(i interface{}) (bool, error) {
69
70	i = indirect(i)
71
72	switch b := i.(type) {
73	case bool:
74		return b, nil
75	case nil:
76		return false, nil
77	case int:
78		if i.(int) != 0 {
79			return true, nil
80		}
81		return false, nil
82	case string:
83		return strconv.ParseBool(i.(string))
84	default:
85		return false, fmt.Errorf("Unable to Cast %#v to bool", i)
86	}
87}
88
89// ToFloat64E casts an empty interface to a float64.
90func ToFloat64E(i interface{}) (float64, error) {
91	i = indirect(i)
92
93	switch s := i.(type) {
94	case float64:
95		return s, nil
96	case float32:
97		return float64(s), nil
98	case int64:
99		return float64(s), nil
100	case int32:
101		return float64(s), nil
102	case int16:
103		return float64(s), nil
104	case int8:
105		return float64(s), nil
106	case int:
107		return float64(s), nil
108	case string:
109		v, err := strconv.ParseFloat(s, 64)
110		if err == nil {
111			return float64(v), nil
112		}
113		return 0.0, fmt.Errorf("Unable to Cast %#v to float", i)
114	default:
115		return 0.0, fmt.Errorf("Unable to Cast %#v to float", i)
116	}
117}
118
119// ToInt64E casts an empty interface to an int64.
120func ToInt64E(i interface{}) (int64, error) {
121	i = indirect(i)
122
123	switch s := i.(type) {
124	case int64:
125		return s, nil
126	case int:
127		return int64(s), nil
128	case int32:
129		return int64(s), nil
130	case int16:
131		return int64(s), nil
132	case int8:
133		return int64(s), nil
134	case string:
135		v, err := strconv.ParseInt(s, 0, 0)
136		if err == nil {
137			return v, nil
138		}
139		return 0, fmt.Errorf("Unable to Cast %#v to int64", i)
140	case float64:
141		return int64(s), nil
142	case bool:
143		if bool(s) {
144			return int64(1), nil
145		}
146		return int64(0), nil
147	case nil:
148		return int64(0), nil
149	default:
150		return int64(0), fmt.Errorf("Unable to Cast %#v to int64", i)
151	}
152}
153
154// ToIntE casts an empty interface to an int.
155func ToIntE(i interface{}) (int, error) {
156	i = indirect(i)
157
158	switch s := i.(type) {
159	case int:
160		return s, nil
161	case int64:
162		return int(s), nil
163	case int32:
164		return int(s), nil
165	case int16:
166		return int(s), nil
167	case int8:
168		return int(s), nil
169	case string:
170		v, err := strconv.ParseInt(s, 0, 0)
171		if err == nil {
172			return int(v), nil
173		}
174		return 0, fmt.Errorf("Unable to Cast %#v to int", i)
175	case float64:
176		return int(s), nil
177	case bool:
178		if bool(s) {
179			return 1, nil
180		}
181		return 0, nil
182	case nil:
183		return 0, nil
184	default:
185		return 0, fmt.Errorf("Unable to Cast %#v to int", i)
186	}
187}
188
189// From html/template/content.go
190// Copyright 2011 The Go Authors. All rights reserved.
191// indirect returns the value, after dereferencing as many times
192// as necessary to reach the base type (or nil).
193func indirect(a interface{}) interface{} {
194	if a == nil {
195		return nil
196	}
197	if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
198		// Avoid creating a reflect.Value if it's not a pointer.
199		return a
200	}
201	v := reflect.ValueOf(a)
202	for v.Kind() == reflect.Ptr && !v.IsNil() {
203		v = v.Elem()
204	}
205	return v.Interface()
206}
207
208// From html/template/content.go
209// Copyright 2011 The Go Authors. All rights reserved.
210// indirectToStringerOrError returns the value, after dereferencing as many times
211// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
212// or error,
213func indirectToStringerOrError(a interface{}) interface{} {
214	if a == nil {
215		return nil
216	}
217
218	var errorType = reflect.TypeOf((*error)(nil)).Elem()
219	var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
220
221	v := reflect.ValueOf(a)
222	for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
223		v = v.Elem()
224	}
225	return v.Interface()
226}
227
228// ToStringE casts an empty interface to a string.
229func ToStringE(i interface{}) (string, error) {
230	i = indirectToStringerOrError(i)
231
232	switch s := i.(type) {
233	case string:
234		return s, nil
235	case bool:
236		return strconv.FormatBool(s), nil
237	case float64:
238		return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil
239	case int64:
240		return strconv.FormatInt(i.(int64), 10), nil
241	case int:
242		return strconv.FormatInt(int64(i.(int)), 10), nil
243	case []byte:
244		return string(s), nil
245	case template.HTML:
246		return string(s), nil
247	case template.URL:
248		return string(s), nil
249	case template.JS:
250		return string(s), nil
251	case template.CSS:
252		return string(s), nil
253	case template.HTMLAttr:
254		return string(s), nil
255	case nil:
256		return "", nil
257	case fmt.Stringer:
258		return s.String(), nil
259	case error:
260		return s.Error(), nil
261	default:
262		return "", fmt.Errorf("Unable to Cast %#v to string", i)
263	}
264}
265
266// ToStringMapStringE casts an empty interface to a map[string]string.
267func ToStringMapStringE(i interface{}) (map[string]string, error) {
268
269	var m = map[string]string{}
270
271	switch v := i.(type) {
272	case map[string]string:
273		return v, nil
274	case map[string]interface{}:
275		for k, val := range v {
276			m[ToString(k)] = ToString(val)
277		}
278		return m, nil
279	case map[interface{}]string:
280		for k, val := range v {
281			m[ToString(k)] = ToString(val)
282		}
283		return m, nil
284	case map[interface{}]interface{}:
285		for k, val := range v {
286			m[ToString(k)] = ToString(val)
287		}
288		return m, nil
289	default:
290		return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i)
291	}
292}
293
294// ToStringMapStringSliceE casts an empty interface to a map[string][]string.
295func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
296
297	var m = map[string][]string{}
298
299	switch v := i.(type) {
300	case map[string][]string:
301		return v, nil
302	case map[string][]interface{}:
303		for k, val := range v {
304			m[ToString(k)] = ToStringSlice(val)
305		}
306		return m, nil
307	case map[string]string:
308		for k, val := range v {
309			m[ToString(k)] = []string{val}
310		}
311	case map[string]interface{}:
312		for k, val := range v {
313			switch vt := val.(type) {
314			case []interface{}:
315				m[ToString(k)] = ToStringSlice(vt)
316			case []string:
317				m[ToString(k)] = vt
318			default:
319				m[ToString(k)] = []string{ToString(val)}
320			}
321		}
322		return m, nil
323	case map[interface{}][]string:
324		for k, val := range v {
325			m[ToString(k)] = ToStringSlice(val)
326		}
327		return m, nil
328	case map[interface{}]string:
329		for k, val := range v {
330			m[ToString(k)] = ToStringSlice(val)
331		}
332		return m, nil
333	case map[interface{}][]interface{}:
334		for k, val := range v {
335			m[ToString(k)] = ToStringSlice(val)
336		}
337		return m, nil
338	case map[interface{}]interface{}:
339		for k, val := range v {
340			key, err := ToStringE(k)
341			if err != nil {
342				return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
343			}
344			value, err := ToStringSliceE(val)
345			if err != nil {
346				return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
347			}
348			m[key] = value
349		}
350	default:
351		return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
352	}
353	return m, nil
354}
355
356// ToStringMapBoolE casts an empty interface to a map[string]bool.
357func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
358
359	var m = map[string]bool{}
360
361	switch v := i.(type) {
362	case map[interface{}]interface{}:
363		for k, val := range v {
364			m[ToString(k)] = ToBool(val)
365		}
366		return m, nil
367	case map[string]interface{}:
368		for k, val := range v {
369			m[ToString(k)] = ToBool(val)
370		}
371		return m, nil
372	case map[string]bool:
373		return v, nil
374	default:
375		return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i)
376	}
377}
378
379// ToStringMapE casts an empty interface to a map[string]interface{}.
380func ToStringMapE(i interface{}) (map[string]interface{}, error) {
381
382	var m = map[string]interface{}{}
383
384	switch v := i.(type) {
385	case map[interface{}]interface{}:
386		for k, val := range v {
387			m[ToString(k)] = val
388		}
389		return m, nil
390	case map[string]interface{}:
391		return v, nil
392	default:
393		return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i)
394	}
395}
396
397// ToSliceE casts an empty interface to a []interface{}.
398func ToSliceE(i interface{}) ([]interface{}, error) {
399
400	var s []interface{}
401
402	switch v := i.(type) {
403	case []interface{}:
404		for _, u := range v {
405			s = append(s, u)
406		}
407		return s, nil
408	case []map[string]interface{}:
409		for _, u := range v {
410			s = append(s, u)
411		}
412		return s, nil
413	default:
414		return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i))
415	}
416}
417
418// ToBoolSliceE casts an empty interface to a []bool.
419func ToBoolSliceE(i interface{}) ([]bool, error) {
420
421	if i == nil {
422		return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i)
423	}
424
425	switch v := i.(type) {
426	case []bool:
427		return v, nil
428	}
429
430	kind := reflect.TypeOf(i).Kind()
431	switch kind {
432	case reflect.Slice, reflect.Array:
433		s := reflect.ValueOf(i)
434		a := make([]bool, s.Len())
435		for j := 0; j < s.Len(); j++ {
436			val, err := ToBoolE(s.Index(j).Interface())
437			if err != nil {
438				return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i)
439			}
440			a[j] = val
441		}
442		return a, nil
443	default:
444		return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i)
445	}
446}
447
448// ToStringSliceE casts an empty interface to a []string.
449func ToStringSliceE(i interface{}) ([]string, error) {
450
451	var a []string
452
453	switch v := i.(type) {
454	case []interface{}:
455		for _, u := range v {
456			a = append(a, ToString(u))
457		}
458		return a, nil
459	case []string:
460		return v, nil
461	case string:
462		return strings.Fields(v), nil
463	case interface{}:
464		str, err := ToStringE(v)
465		if err != nil {
466			return a, fmt.Errorf("Unable to Cast %#v to []string", i)
467		}
468		return []string{str}, nil
469	default:
470		return a, fmt.Errorf("Unable to Cast %#v to []string", i)
471	}
472}
473
474// ToIntSliceE casts an empty interface to a []int.
475func ToIntSliceE(i interface{}) ([]int, error) {
476
477	if i == nil {
478		return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
479	}
480
481	switch v := i.(type) {
482	case []int:
483		return v, nil
484	}
485
486	kind := reflect.TypeOf(i).Kind()
487	switch kind {
488	case reflect.Slice, reflect.Array:
489		s := reflect.ValueOf(i)
490		a := make([]int, s.Len())
491		for j := 0; j < s.Len(); j++ {
492			val, err := ToIntE(s.Index(j).Interface())
493			if err != nil {
494				return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
495			}
496			a[j] = val
497		}
498		return a, nil
499	default:
500		return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
501	}
502}
503
504// StringToDate casts an empty interface to a time.Time.
505func StringToDate(s string) (time.Time, error) {
506	return parseDateWith(s, []string{
507		time.RFC3339,
508		"2006-01-02T15:04:05", // iso8601 without timezone
509		time.RFC1123Z,
510		time.RFC1123,
511		time.RFC822Z,
512		time.RFC822,
513		time.ANSIC,
514		time.UnixDate,
515		time.RubyDate,
516		"2006-01-02 15:04:05Z07:00",
517		"02 Jan 06 15:04 MST",
518		"2006-01-02",
519		"02 Jan 2006",
520		"2006-01-02 15:04:05 -07:00",
521		"2006-01-02 15:04:05 -0700",
522		"2006-01-02 15:04:05",
523	})
524}
525
526func parseDateWith(s string, dates []string) (d time.Time, e error) {
527	for _, dateType := range dates {
528		if d, e = time.Parse(dateType, s); e == nil {
529			return
530		}
531	}
532	return d, fmt.Errorf("Unable to parse date: %s", s)
533}
534