|  | // Copyright © 2014 Steve Francia <spf@spf13.com>. | 
|  | // | 
|  | // Use of this source code is governed by an MIT-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package cast | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "html/template" | 
|  | "reflect" | 
|  | "strconv" | 
|  | "strings" | 
|  | "time" | 
|  | ) | 
|  |  | 
|  | // ToTimeE casts an empty interface to time.Time. | 
|  | func ToTimeE(i interface{}) (tim time.Time, err error) { | 
|  | i = indirect(i) | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case time.Time: | 
|  | return v, nil | 
|  | case string: | 
|  | d, e := StringToDate(v) | 
|  | if e == nil { | 
|  | return d, nil | 
|  | } | 
|  | return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e) | 
|  | case int: | 
|  | return time.Unix(int64(v), 0), nil | 
|  | case int32: | 
|  | return time.Unix(int64(v), 0), nil | 
|  | case int64: | 
|  | return time.Unix(v, 0), nil | 
|  | default: | 
|  | return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToDurationE casts an empty interface to time.Duration. | 
|  | func ToDurationE(i interface{}) (d time.Duration, err error) { | 
|  | i = indirect(i) | 
|  |  | 
|  | switch s := i.(type) { | 
|  | case time.Duration: | 
|  | return s, nil | 
|  | case int64, int32, int16, int8, int: | 
|  | d = time.Duration(ToInt64(s)) | 
|  | return | 
|  | case float32, float64: | 
|  | d = time.Duration(ToFloat64(s)) | 
|  | return | 
|  | case string: | 
|  | if strings.ContainsAny(s, "nsuµmh") { | 
|  | d, err = time.ParseDuration(s) | 
|  | } else { | 
|  | d, err = time.ParseDuration(s + "ns") | 
|  | } | 
|  | return | 
|  | default: | 
|  | err = fmt.Errorf("Unable to Cast %#v to Duration\n", i) | 
|  | return | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToBoolE casts an empty interface to a bool. | 
|  | func ToBoolE(i interface{}) (bool, error) { | 
|  |  | 
|  | i = indirect(i) | 
|  |  | 
|  | switch b := i.(type) { | 
|  | case bool: | 
|  | return b, nil | 
|  | case nil: | 
|  | return false, nil | 
|  | case int: | 
|  | if i.(int) != 0 { | 
|  | return true, nil | 
|  | } | 
|  | return false, nil | 
|  | case string: | 
|  | return strconv.ParseBool(i.(string)) | 
|  | default: | 
|  | return false, fmt.Errorf("Unable to Cast %#v to bool", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToFloat64E casts an empty interface to a float64. | 
|  | func ToFloat64E(i interface{}) (float64, error) { | 
|  | i = indirect(i) | 
|  |  | 
|  | switch s := i.(type) { | 
|  | case float64: | 
|  | return s, nil | 
|  | case float32: | 
|  | return float64(s), nil | 
|  | case int64: | 
|  | return float64(s), nil | 
|  | case int32: | 
|  | return float64(s), nil | 
|  | case int16: | 
|  | return float64(s), nil | 
|  | case int8: | 
|  | return float64(s), nil | 
|  | case int: | 
|  | return float64(s), nil | 
|  | case string: | 
|  | v, err := strconv.ParseFloat(s, 64) | 
|  | if err == nil { | 
|  | return float64(v), nil | 
|  | } | 
|  | return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) | 
|  | default: | 
|  | return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToInt64E casts an empty interface to an int64. | 
|  | func ToInt64E(i interface{}) (int64, error) { | 
|  | i = indirect(i) | 
|  |  | 
|  | switch s := i.(type) { | 
|  | case int64: | 
|  | return s, nil | 
|  | case int: | 
|  | return int64(s), nil | 
|  | case int32: | 
|  | return int64(s), nil | 
|  | case int16: | 
|  | return int64(s), nil | 
|  | case int8: | 
|  | return int64(s), nil | 
|  | case string: | 
|  | v, err := strconv.ParseInt(s, 0, 0) | 
|  | if err == nil { | 
|  | return v, nil | 
|  | } | 
|  | return 0, fmt.Errorf("Unable to Cast %#v to int64", i) | 
|  | case float64: | 
|  | return int64(s), nil | 
|  | case bool: | 
|  | if bool(s) { | 
|  | return int64(1), nil | 
|  | } | 
|  | return int64(0), nil | 
|  | case nil: | 
|  | return int64(0), nil | 
|  | default: | 
|  | return int64(0), fmt.Errorf("Unable to Cast %#v to int64", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToIntE casts an empty interface to an int. | 
|  | func ToIntE(i interface{}) (int, error) { | 
|  | i = indirect(i) | 
|  |  | 
|  | switch s := i.(type) { | 
|  | case int: | 
|  | return s, nil | 
|  | case int64: | 
|  | return int(s), nil | 
|  | case int32: | 
|  | return int(s), nil | 
|  | case int16: | 
|  | return int(s), nil | 
|  | case int8: | 
|  | return int(s), nil | 
|  | case string: | 
|  | v, err := strconv.ParseInt(s, 0, 0) | 
|  | if err == nil { | 
|  | return int(v), nil | 
|  | } | 
|  | return 0, fmt.Errorf("Unable to Cast %#v to int", i) | 
|  | case float64: | 
|  | return int(s), nil | 
|  | case bool: | 
|  | if bool(s) { | 
|  | return 1, nil | 
|  | } | 
|  | return 0, nil | 
|  | case nil: | 
|  | return 0, nil | 
|  | default: | 
|  | return 0, fmt.Errorf("Unable to Cast %#v to int", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // From html/template/content.go | 
|  | // Copyright 2011 The Go Authors. All rights reserved. | 
|  | // indirect returns the value, after dereferencing as many times | 
|  | // as necessary to reach the base type (or nil). | 
|  | func indirect(a interface{}) interface{} { | 
|  | if a == nil { | 
|  | return nil | 
|  | } | 
|  | if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { | 
|  | // Avoid creating a reflect.Value if it's not a pointer. | 
|  | return a | 
|  | } | 
|  | v := reflect.ValueOf(a) | 
|  | for v.Kind() == reflect.Ptr && !v.IsNil() { | 
|  | v = v.Elem() | 
|  | } | 
|  | return v.Interface() | 
|  | } | 
|  |  | 
|  | // From html/template/content.go | 
|  | // Copyright 2011 The Go Authors. All rights reserved. | 
|  | // indirectToStringerOrError returns the value, after dereferencing as many times | 
|  | // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer | 
|  | // or error, | 
|  | func indirectToStringerOrError(a interface{}) interface{} { | 
|  | if a == nil { | 
|  | return nil | 
|  | } | 
|  |  | 
|  | var errorType = reflect.TypeOf((*error)(nil)).Elem() | 
|  | var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() | 
|  |  | 
|  | v := reflect.ValueOf(a) | 
|  | for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { | 
|  | v = v.Elem() | 
|  | } | 
|  | return v.Interface() | 
|  | } | 
|  |  | 
|  | // ToStringE casts an empty interface to a string. | 
|  | func ToStringE(i interface{}) (string, error) { | 
|  | i = indirectToStringerOrError(i) | 
|  |  | 
|  | switch s := i.(type) { | 
|  | case string: | 
|  | return s, nil | 
|  | case bool: | 
|  | return strconv.FormatBool(s), nil | 
|  | case float64: | 
|  | return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil | 
|  | case int64: | 
|  | return strconv.FormatInt(i.(int64), 10), nil | 
|  | case int: | 
|  | return strconv.FormatInt(int64(i.(int)), 10), nil | 
|  | case []byte: | 
|  | return string(s), nil | 
|  | case template.HTML: | 
|  | return string(s), nil | 
|  | case template.URL: | 
|  | return string(s), nil | 
|  | case template.JS: | 
|  | return string(s), nil | 
|  | case template.CSS: | 
|  | return string(s), nil | 
|  | case template.HTMLAttr: | 
|  | return string(s), nil | 
|  | case nil: | 
|  | return "", nil | 
|  | case fmt.Stringer: | 
|  | return s.String(), nil | 
|  | case error: | 
|  | return s.Error(), nil | 
|  | default: | 
|  | return "", fmt.Errorf("Unable to Cast %#v to string", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToStringMapStringE casts an empty interface to a map[string]string. | 
|  | func ToStringMapStringE(i interface{}) (map[string]string, error) { | 
|  |  | 
|  | var m = map[string]string{} | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case map[string]string: | 
|  | return v, nil | 
|  | case map[string]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToString(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[interface{}]string: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToString(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[interface{}]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToString(val) | 
|  | } | 
|  | return m, nil | 
|  | default: | 
|  | return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToStringMapStringSliceE casts an empty interface to a map[string][]string. | 
|  | func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { | 
|  |  | 
|  | var m = map[string][]string{} | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case map[string][]string: | 
|  | return v, nil | 
|  | case map[string][]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToStringSlice(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[string]string: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = []string{val} | 
|  | } | 
|  | case map[string]interface{}: | 
|  | for k, val := range v { | 
|  | switch vt := val.(type) { | 
|  | case []interface{}: | 
|  | m[ToString(k)] = ToStringSlice(vt) | 
|  | case []string: | 
|  | m[ToString(k)] = vt | 
|  | default: | 
|  | m[ToString(k)] = []string{ToString(val)} | 
|  | } | 
|  | } | 
|  | return m, nil | 
|  | case map[interface{}][]string: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToStringSlice(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[interface{}]string: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToStringSlice(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[interface{}][]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToStringSlice(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[interface{}]interface{}: | 
|  | for k, val := range v { | 
|  | key, err := ToStringE(k) | 
|  | if err != nil { | 
|  | return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) | 
|  | } | 
|  | value, err := ToStringSliceE(val) | 
|  | if err != nil { | 
|  | return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) | 
|  | } | 
|  | m[key] = value | 
|  | } | 
|  | default: | 
|  | return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) | 
|  | } | 
|  | return m, nil | 
|  | } | 
|  |  | 
|  | // ToStringMapBoolE casts an empty interface to a map[string]bool. | 
|  | func ToStringMapBoolE(i interface{}) (map[string]bool, error) { | 
|  |  | 
|  | var m = map[string]bool{} | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case map[interface{}]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToBool(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[string]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = ToBool(val) | 
|  | } | 
|  | return m, nil | 
|  | case map[string]bool: | 
|  | return v, nil | 
|  | default: | 
|  | return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToStringMapE casts an empty interface to a map[string]interface{}. | 
|  | func ToStringMapE(i interface{}) (map[string]interface{}, error) { | 
|  |  | 
|  | var m = map[string]interface{}{} | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case map[interface{}]interface{}: | 
|  | for k, val := range v { | 
|  | m[ToString(k)] = val | 
|  | } | 
|  | return m, nil | 
|  | case map[string]interface{}: | 
|  | return v, nil | 
|  | default: | 
|  | return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToSliceE casts an empty interface to a []interface{}. | 
|  | func ToSliceE(i interface{}) ([]interface{}, error) { | 
|  |  | 
|  | var s []interface{} | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case []interface{}: | 
|  | for _, u := range v { | 
|  | s = append(s, u) | 
|  | } | 
|  | return s, nil | 
|  | case []map[string]interface{}: | 
|  | for _, u := range v { | 
|  | s = append(s, u) | 
|  | } | 
|  | return s, nil | 
|  | default: | 
|  | return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i)) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToBoolSliceE casts an empty interface to a []bool. | 
|  | func ToBoolSliceE(i interface{}) ([]bool, error) { | 
|  |  | 
|  | if i == nil { | 
|  | return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i) | 
|  | } | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case []bool: | 
|  | return v, nil | 
|  | } | 
|  |  | 
|  | kind := reflect.TypeOf(i).Kind() | 
|  | switch kind { | 
|  | case reflect.Slice, reflect.Array: | 
|  | s := reflect.ValueOf(i) | 
|  | a := make([]bool, s.Len()) | 
|  | for j := 0; j < s.Len(); j++ { | 
|  | val, err := ToBoolE(s.Index(j).Interface()) | 
|  | if err != nil { | 
|  | return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i) | 
|  | } | 
|  | a[j] = val | 
|  | } | 
|  | return a, nil | 
|  | default: | 
|  | return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToStringSliceE casts an empty interface to a []string. | 
|  | func ToStringSliceE(i interface{}) ([]string, error) { | 
|  |  | 
|  | var a []string | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case []interface{}: | 
|  | for _, u := range v { | 
|  | a = append(a, ToString(u)) | 
|  | } | 
|  | return a, nil | 
|  | case []string: | 
|  | return v, nil | 
|  | case string: | 
|  | return strings.Fields(v), nil | 
|  | case interface{}: | 
|  | str, err := ToStringE(v) | 
|  | if err != nil { | 
|  | return a, fmt.Errorf("Unable to Cast %#v to []string", i) | 
|  | } | 
|  | return []string{str}, nil | 
|  | default: | 
|  | return a, fmt.Errorf("Unable to Cast %#v to []string", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // ToIntSliceE casts an empty interface to a []int. | 
|  | func ToIntSliceE(i interface{}) ([]int, error) { | 
|  |  | 
|  | if i == nil { | 
|  | return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) | 
|  | } | 
|  |  | 
|  | switch v := i.(type) { | 
|  | case []int: | 
|  | return v, nil | 
|  | } | 
|  |  | 
|  | kind := reflect.TypeOf(i).Kind() | 
|  | switch kind { | 
|  | case reflect.Slice, reflect.Array: | 
|  | s := reflect.ValueOf(i) | 
|  | a := make([]int, s.Len()) | 
|  | for j := 0; j < s.Len(); j++ { | 
|  | val, err := ToIntE(s.Index(j).Interface()) | 
|  | if err != nil { | 
|  | return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) | 
|  | } | 
|  | a[j] = val | 
|  | } | 
|  | return a, nil | 
|  | default: | 
|  | return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) | 
|  | } | 
|  | } | 
|  |  | 
|  | // StringToDate casts an empty interface to a time.Time. | 
|  | func StringToDate(s string) (time.Time, error) { | 
|  | return parseDateWith(s, []string{ | 
|  | time.RFC3339, | 
|  | "2006-01-02T15:04:05", // iso8601 without timezone | 
|  | time.RFC1123Z, | 
|  | time.RFC1123, | 
|  | time.RFC822Z, | 
|  | time.RFC822, | 
|  | time.RFC850, | 
|  | time.ANSIC, | 
|  | time.UnixDate, | 
|  | time.RubyDate, | 
|  | "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() | 
|  | "2006-01-02", | 
|  | "02 Jan 2006", | 
|  | "2006-01-02 15:04:05 -07:00", | 
|  | "2006-01-02 15:04:05 -0700", | 
|  | "2006-01-02 15:04:05", | 
|  | time.Kitchen, | 
|  | time.Stamp, | 
|  | time.StampMilli, | 
|  | time.StampMicro, | 
|  | time.StampNano, | 
|  | }) | 
|  | } | 
|  |  | 
|  | func parseDateWith(s string, dates []string) (d time.Time, e error) { | 
|  | for _, dateType := range dates { | 
|  | if d, e = time.Parse(dateType, s); e == nil { | 
|  | return | 
|  | } | 
|  | } | 
|  | return d, fmt.Errorf("Unable to parse date: %s", s) | 
|  | } |