Files
kubesphere/vendor/github.com/spf13/cast/caste.go
Jeff 96d2ac4112 This is a huge commit, it does following things:
1. refactor kubesphere dependency service client creation, we can
disable dependency by config
2. dependencies can be configured by configuration file
3. refactor cmd package using cobra.Command, so we can use hypersphere
to invoke command sepearately. Later we only need to build one image to
contains all kubesphere core components. One command to rule them all!
4. live reloading configuration currently not implemented
2019-09-11 19:53:35 +08:00

1250 lines
27 KiB
Go

// 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 (
"encoding/json"
"errors"
"fmt"
"html/template"
"reflect"
"strconv"
"strings"
"time"
)
var errNegativeNotAllowed = errors.New("unable to cast negative value")
// ToTimeE casts an interface to a time.Time type.
func ToTimeE(i interface{}) (tim time.Time, err error) {
i = indirect(i)
switch v := i.(type) {
case time.Time:
return v, nil
case string:
return StringToDate(v)
case int:
return time.Unix(int64(v), 0), nil
case int64:
return time.Unix(v, 0), nil
case int32:
return time.Unix(int64(v), 0), nil
case uint:
return time.Unix(int64(v), 0), nil
case uint64:
return time.Unix(int64(v), 0), nil
case uint32:
return time.Unix(int64(v), 0), nil
default:
return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i)
}
}
// ToDurationE casts an interface to a time.Duration type.
func ToDurationE(i interface{}) (d time.Duration, err error) {
i = indirect(i)
switch s := i.(type) {
case time.Duration:
return s, nil
case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8:
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 of type %T to Duration", i, i)
return
}
}
// ToBoolE casts an interface to a bool type.
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 of type %T to bool", i, i)
}
}
// ToFloat64E casts an interface to a float64 type.
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 int:
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 uint:
return float64(s), nil
case uint64:
return float64(s), nil
case uint32:
return float64(s), nil
case uint16:
return float64(s), nil
case uint8:
return float64(s), nil
case string:
v, err := strconv.ParseFloat(s, 64)
if err == nil {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
}
}
// ToFloat32E casts an interface to a float32 type.
func ToFloat32E(i interface{}) (float32, error) {
i = indirect(i)
switch s := i.(type) {
case float64:
return float32(s), nil
case float32:
return s, nil
case int:
return float32(s), nil
case int64:
return float32(s), nil
case int32:
return float32(s), nil
case int16:
return float32(s), nil
case int8:
return float32(s), nil
case uint:
return float32(s), nil
case uint64:
return float32(s), nil
case uint32:
return float32(s), nil
case uint16:
return float32(s), nil
case uint8:
return float32(s), nil
case string:
v, err := strconv.ParseFloat(s, 32)
if err == nil {
return float32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
}
}
// ToInt64E casts an interface to an int64 type.
func ToInt64E(i interface{}) (int64, error) {
i = indirect(i)
switch s := i.(type) {
case int:
return int64(s), nil
case int64:
return s, nil
case int32:
return int64(s), nil
case int16:
return int64(s), nil
case int8:
return int64(s), nil
case uint:
return int64(s), nil
case uint64:
return int64(s), nil
case uint32:
return int64(s), nil
case uint16:
return int64(s), nil
case uint8:
return int64(s), nil
case float64:
return int64(s), nil
case float32:
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 of type %T to int64", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i)
}
}
// ToInt32E casts an interface to an int32 type.
func ToInt32E(i interface{}) (int32, error) {
i = indirect(i)
switch s := i.(type) {
case int:
return int32(s), nil
case int64:
return int32(s), nil
case int32:
return s, nil
case int16:
return int32(s), nil
case int8:
return int32(s), nil
case uint:
return int32(s), nil
case uint64:
return int32(s), nil
case uint32:
return int32(s), nil
case uint16:
return int32(s), nil
case uint8:
return int32(s), nil
case float64:
return int32(s), nil
case float32:
return int32(s), nil
case string:
v, err := strconv.ParseInt(s, 0, 0)
if err == nil {
return int32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i)
}
}
// ToInt16E casts an interface to an int16 type.
func ToInt16E(i interface{}) (int16, error) {
i = indirect(i)
switch s := i.(type) {
case int:
return int16(s), nil
case int64:
return int16(s), nil
case int32:
return int16(s), nil
case int16:
return s, nil
case int8:
return int16(s), nil
case uint:
return int16(s), nil
case uint64:
return int16(s), nil
case uint32:
return int16(s), nil
case uint16:
return int16(s), nil
case uint8:
return int16(s), nil
case float64:
return int16(s), nil
case float32:
return int16(s), nil
case string:
v, err := strconv.ParseInt(s, 0, 0)
if err == nil {
return int16(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i)
}
}
// ToInt8E casts an interface to an int8 type.
func ToInt8E(i interface{}) (int8, error) {
i = indirect(i)
switch s := i.(type) {
case int:
return int8(s), nil
case int64:
return int8(s), nil
case int32:
return int8(s), nil
case int16:
return int8(s), nil
case int8:
return s, nil
case uint:
return int8(s), nil
case uint64:
return int8(s), nil
case uint32:
return int8(s), nil
case uint16:
return int8(s), nil
case uint8:
return int8(s), nil
case float64:
return int8(s), nil
case float32:
return int8(s), nil
case string:
v, err := strconv.ParseInt(s, 0, 0)
if err == nil {
return int8(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i)
}
}
// ToIntE casts an interface to an int type.
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 uint:
return int(s), nil
case uint64:
return int(s), nil
case uint32:
return int(s), nil
case uint16:
return int(s), nil
case uint8:
return int(s), nil
case float64:
return int(s), nil
case float32:
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 of type %T to int", i, i)
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i)
}
}
// ToUintE casts an interface to a uint type.
func ToUintE(i interface{}) (uint, error) {
i = indirect(i)
switch s := i.(type) {
case string:
v, err := strconv.ParseUint(s, 0, 0)
if err == nil {
return uint(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint: %s", i, err)
case int:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case int64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case int32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case int16:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case int8:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case uint:
return s, nil
case uint64:
return uint(s), nil
case uint32:
return uint(s), nil
case uint16:
return uint(s), nil
case uint8:
return uint(s), nil
case float64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case float32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint(s), nil
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i)
}
}
// ToUint64E casts an interface to a uint64 type.
func ToUint64E(i interface{}) (uint64, error) {
i = indirect(i)
switch s := i.(type) {
case string:
v, err := strconv.ParseUint(s, 0, 64)
if err == nil {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v to uint64: %s", i, err)
case int:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case int64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case int32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case int16:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case int8:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case uint:
return uint64(s), nil
case uint64:
return s, nil
case uint32:
return uint64(s), nil
case uint16:
return uint64(s), nil
case uint8:
return uint64(s), nil
case float32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case float64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
}
}
// ToUint32E casts an interface to a uint32 type.
func ToUint32E(i interface{}) (uint32, error) {
i = indirect(i)
switch s := i.(type) {
case string:
v, err := strconv.ParseUint(s, 0, 32)
if err == nil {
return uint32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint32: %s", i, err)
case int:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case int64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case int32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case int16:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case int8:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case uint:
return uint32(s), nil
case uint64:
return uint32(s), nil
case uint32:
return s, nil
case uint16:
return uint32(s), nil
case uint8:
return uint32(s), nil
case float64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case float32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i)
}
}
// ToUint16E casts an interface to a uint16 type.
func ToUint16E(i interface{}) (uint16, error) {
i = indirect(i)
switch s := i.(type) {
case string:
v, err := strconv.ParseUint(s, 0, 16)
if err == nil {
return uint16(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint16: %s", i, err)
case int:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case int64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case int32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case int16:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case int8:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case uint:
return uint16(s), nil
case uint64:
return uint16(s), nil
case uint32:
return uint16(s), nil
case uint16:
return s, nil
case uint8:
return uint16(s), nil
case float64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case float32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i)
}
}
// ToUint8E casts an interface to a uint type.
func ToUint8E(i interface{}) (uint8, error) {
i = indirect(i)
switch s := i.(type) {
case string:
v, err := strconv.ParseUint(s, 0, 8)
if err == nil {
return uint8(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint8: %s", i, err)
case int:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case int64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case int32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case int16:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case int8:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case uint:
return uint8(s), nil
case uint64:
return uint8(s), nil
case uint32:
return uint8(s), nil
case uint16:
return uint8(s), nil
case uint8:
return s, nil
case float64:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case float32:
if s < 0 {
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case bool:
if s {
return 1, nil
}
return 0, nil
case nil:
return 0, nil
default:
return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, 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 interface to a string type.
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(s, 'f', -1, 64), nil
case float32:
return strconv.FormatFloat(float64(s), 'f', -1, 32), nil
case int:
return strconv.Itoa(s), nil
case int64:
return strconv.FormatInt(s, 10), nil
case int32:
return strconv.Itoa(int(s)), nil
case int16:
return strconv.FormatInt(int64(s), 10), nil
case int8:
return strconv.FormatInt(int64(s), 10), nil
case uint:
return strconv.FormatInt(int64(s), 10), nil
case uint64:
return strconv.FormatInt(int64(s), 10), nil
case uint32:
return strconv.FormatInt(int64(s), 10), nil
case uint16:
return strconv.FormatInt(int64(s), 10), nil
case uint8:
return strconv.FormatInt(int64(s), 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 of type %T to string", i, i)
}
}
// ToStringMapStringE casts an interface to a map[string]string type.
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
case string:
err := jsonStringToObject(v, &m)
return m, err
default:
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i)
}
}
// ToStringMapStringSliceE casts an interface to a map[string][]string type.
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 of type %T to map[string][]string", i, i)
}
value, err := ToStringSliceE(val)
if err != nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
}
m[key] = value
}
case string:
err := jsonStringToObject(v, &m)
return m, err
default:
return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
}
return m, nil
}
// ToStringMapBoolE casts an interface to a map[string]bool type.
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
case string:
err := jsonStringToObject(v, &m)
return m, err
default:
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i)
}
}
// ToStringMapE casts an interface to a map[string]interface{} type.
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
case string:
err := jsonStringToObject(v, &m)
return m, err
default:
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i)
}
}
// ToStringMapIntE casts an interface to a map[string]int{} type.
func ToStringMapIntE(i interface{}) (map[string]int, error) {
var m = map[string]int{}
if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
}
switch v := i.(type) {
case map[interface{}]interface{}:
for k, val := range v {
m[ToString(k)] = ToInt(val)
}
return m, nil
case map[string]interface{}:
for k, val := range v {
m[k] = ToInt(val)
}
return m, nil
case map[string]int:
return v, nil
case string:
err := jsonStringToObject(v, &m)
return m, err
}
if reflect.TypeOf(i).Kind() != reflect.Map {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
}
mVal := reflect.ValueOf(m)
v := reflect.ValueOf(i)
for _, keyVal := range v.MapKeys() {
val, err := ToIntE(v.MapIndex(keyVal).Interface())
if err != nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
}
mVal.SetMapIndex(keyVal, reflect.ValueOf(val))
}
return m, nil
}
// ToStringMapInt64E casts an interface to a map[string]int64{} type.
func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
var m = map[string]int64{}
if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
}
switch v := i.(type) {
case map[interface{}]interface{}:
for k, val := range v {
m[ToString(k)] = ToInt64(val)
}
return m, nil
case map[string]interface{}:
for k, val := range v {
m[k] = ToInt64(val)
}
return m, nil
case map[string]int64:
return v, nil
case string:
err := jsonStringToObject(v, &m)
return m, err
}
if reflect.TypeOf(i).Kind() != reflect.Map {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
}
mVal := reflect.ValueOf(m)
v := reflect.ValueOf(i)
for _, keyVal := range v.MapKeys() {
val, err := ToInt64E(v.MapIndex(keyVal).Interface())
if err != nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
}
mVal.SetMapIndex(keyVal, reflect.ValueOf(val))
}
return m, nil
}
// ToSliceE casts an interface to a []interface{} type.
func ToSliceE(i interface{}) ([]interface{}, error) {
var s []interface{}
switch v := i.(type) {
case []interface{}:
return append(s, v...), 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 %T to []interface{}", i, i)
}
}
// ToBoolSliceE casts an interface to a []bool type.
func ToBoolSliceE(i interface{}) ([]bool, error) {
if i == nil {
return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, 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 of type %T to []bool", i, i)
}
a[j] = val
}
return a, nil
default:
return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i)
}
}
// ToStringSliceE casts an interface to a []string type.
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 of type %T to []string", i, i)
}
return []string{str}, nil
default:
return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i)
}
}
// ToIntSliceE casts an interface to a []int type.
func ToIntSliceE(i interface{}) ([]int, error) {
if i == nil {
return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, 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 of type %T to []int", i, i)
}
a[j] = val
}
return a, nil
default:
return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i)
}
}
// ToDurationSliceE casts an interface to a []time.Duration type.
func ToDurationSliceE(i interface{}) ([]time.Duration, error) {
if i == nil {
return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i)
}
switch v := i.(type) {
case []time.Duration:
return v, nil
}
kind := reflect.TypeOf(i).Kind()
switch kind {
case reflect.Slice, reflect.Array:
s := reflect.ValueOf(i)
a := make([]time.Duration, s.Len())
for j := 0; j < s.Len(); j++ {
val, err := ToDurationE(s.Index(j).Interface())
if err != nil {
return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i)
}
a[j] = val
}
return a, nil
default:
return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i)
}
}
// StringToDate attempts to parse a string into a time.Time type using a
// predefined list of formats. If no suitable format is found, an error is
// returned.
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-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon
"2006-01-02 15:04:05 -07:00",
"2006-01-02 15:04:05 -0700",
"2006-01-02 15:04:05Z07:00", // RFC3339 without T
"2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon
"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)
}
// jsonStringToObject attempts to unmarshall a string as JSON into
// the object passed as pointer.
func jsonStringToObject(s string, v interface{}) error {
data := []byte(s)
return json.Unmarshal(data, v)
}