mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-06 09:06:44 +00:00
![Paddy](/assets/img/avatar_default.png)
Switch to using Go modules. This migrates our vendor.json to use Go 1.11's modules system, and replaces the vendor folder with the output of go mod vendor. The vendored code should remain basically the same; I believe some tree shaking of packages and support scripts/licenses/READMEs/etc. happened. This also fixes Travis and our Makefile to no longer use govendor.
218 lines
5.1 KiB
Go
218 lines
5.1 KiB
Go
package mapstructure
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns
|
|
// it into the proper DecodeHookFunc type, such as DecodeHookFuncType.
|
|
func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc {
|
|
// Create variables here so we can reference them with the reflect pkg
|
|
var f1 DecodeHookFuncType
|
|
var f2 DecodeHookFuncKind
|
|
|
|
// Fill in the variables into this interface and the rest is done
|
|
// automatically using the reflect package.
|
|
potential := []interface{}{f1, f2}
|
|
|
|
v := reflect.ValueOf(h)
|
|
vt := v.Type()
|
|
for _, raw := range potential {
|
|
pt := reflect.ValueOf(raw).Type()
|
|
if vt.ConvertibleTo(pt) {
|
|
return v.Convert(pt).Interface()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DecodeHookExec executes the given decode hook. This should be used
|
|
// since it'll naturally degrade to the older backwards compatible DecodeHookFunc
|
|
// that took reflect.Kind instead of reflect.Type.
|
|
func DecodeHookExec(
|
|
raw DecodeHookFunc,
|
|
from reflect.Type, to reflect.Type,
|
|
data interface{}) (interface{}, error) {
|
|
switch f := typedDecodeHook(raw).(type) {
|
|
case DecodeHookFuncType:
|
|
return f(from, to, data)
|
|
case DecodeHookFuncKind:
|
|
return f(from.Kind(), to.Kind(), data)
|
|
default:
|
|
return nil, errors.New("invalid decode hook signature")
|
|
}
|
|
}
|
|
|
|
// ComposeDecodeHookFunc creates a single DecodeHookFunc that
|
|
// automatically composes multiple DecodeHookFuncs.
|
|
//
|
|
// The composed funcs are called in order, with the result of the
|
|
// previous transformation.
|
|
func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc {
|
|
return func(
|
|
f reflect.Type,
|
|
t reflect.Type,
|
|
data interface{}) (interface{}, error) {
|
|
var err error
|
|
for _, f1 := range fs {
|
|
data, err = DecodeHookExec(f1, f, t, data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Modify the from kind to be correct with the new data
|
|
f = nil
|
|
if val := reflect.ValueOf(data); val.IsValid() {
|
|
f = val.Type()
|
|
}
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
}
|
|
|
|
// StringToSliceHookFunc returns a DecodeHookFunc that converts
|
|
// string to []string by splitting on the given sep.
|
|
func StringToSliceHookFunc(sep string) DecodeHookFunc {
|
|
return func(
|
|
f reflect.Kind,
|
|
t reflect.Kind,
|
|
data interface{}) (interface{}, error) {
|
|
if f != reflect.String || t != reflect.Slice {
|
|
return data, nil
|
|
}
|
|
|
|
raw := data.(string)
|
|
if raw == "" {
|
|
return []string{}, nil
|
|
}
|
|
|
|
return strings.Split(raw, sep), nil
|
|
}
|
|
}
|
|
|
|
// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts
|
|
// strings to time.Duration.
|
|
func StringToTimeDurationHookFunc() DecodeHookFunc {
|
|
return func(
|
|
f reflect.Type,
|
|
t reflect.Type,
|
|
data interface{}) (interface{}, error) {
|
|
if f.Kind() != reflect.String {
|
|
return data, nil
|
|
}
|
|
if t != reflect.TypeOf(time.Duration(5)) {
|
|
return data, nil
|
|
}
|
|
|
|
// Convert it by parsing
|
|
return time.ParseDuration(data.(string))
|
|
}
|
|
}
|
|
|
|
// StringToIPHookFunc returns a DecodeHookFunc that converts
|
|
// strings to net.IP
|
|
func StringToIPHookFunc() DecodeHookFunc {
|
|
return func(
|
|
f reflect.Type,
|
|
t reflect.Type,
|
|
data interface{}) (interface{}, error) {
|
|
if f.Kind() != reflect.String {
|
|
return data, nil
|
|
}
|
|
if t != reflect.TypeOf(net.IP{}) {
|
|
return data, nil
|
|
}
|
|
|
|
// Convert it by parsing
|
|
ip := net.ParseIP(data.(string))
|
|
if ip == nil {
|
|
return net.IP{}, fmt.Errorf("failed parsing ip %v", data)
|
|
}
|
|
|
|
return ip, nil
|
|
}
|
|
}
|
|
|
|
// StringToIPNetHookFunc returns a DecodeHookFunc that converts
|
|
// strings to net.IPNet
|
|
func StringToIPNetHookFunc() DecodeHookFunc {
|
|
return func(
|
|
f reflect.Type,
|
|
t reflect.Type,
|
|
data interface{}) (interface{}, error) {
|
|
if f.Kind() != reflect.String {
|
|
return data, nil
|
|
}
|
|
if t != reflect.TypeOf(net.IPNet{}) {
|
|
return data, nil
|
|
}
|
|
|
|
// Convert it by parsing
|
|
_, net, err := net.ParseCIDR(data.(string))
|
|
return net, err
|
|
}
|
|
}
|
|
|
|
// StringToTimeHookFunc returns a DecodeHookFunc that converts
|
|
// strings to time.Time.
|
|
func StringToTimeHookFunc(layout string) DecodeHookFunc {
|
|
return func(
|
|
f reflect.Type,
|
|
t reflect.Type,
|
|
data interface{}) (interface{}, error) {
|
|
if f.Kind() != reflect.String {
|
|
return data, nil
|
|
}
|
|
if t != reflect.TypeOf(time.Time{}) {
|
|
return data, nil
|
|
}
|
|
|
|
// Convert it by parsing
|
|
return time.Parse(layout, data.(string))
|
|
}
|
|
}
|
|
|
|
// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to
|
|
// the decoder.
|
|
//
|
|
// Note that this is significantly different from the WeaklyTypedInput option
|
|
// of the DecoderConfig.
|
|
func WeaklyTypedHook(
|
|
f reflect.Kind,
|
|
t reflect.Kind,
|
|
data interface{}) (interface{}, error) {
|
|
dataVal := reflect.ValueOf(data)
|
|
switch t {
|
|
case reflect.String:
|
|
switch f {
|
|
case reflect.Bool:
|
|
if dataVal.Bool() {
|
|
return "1", nil
|
|
}
|
|
return "0", nil
|
|
case reflect.Float32:
|
|
return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil
|
|
case reflect.Int:
|
|
return strconv.FormatInt(dataVal.Int(), 10), nil
|
|
case reflect.Slice:
|
|
dataType := dataVal.Type()
|
|
elemKind := dataType.Elem().Kind()
|
|
if elemKind == reflect.Uint8 {
|
|
return string(dataVal.Interface().([]uint8)), nil
|
|
}
|
|
case reflect.Uint:
|
|
return strconv.FormatUint(dataVal.Uint(), 10), nil
|
|
}
|
|
}
|
|
|
|
return data, nil
|
|
}
|