From af7a68fa8a6658931cc4640c519a9d1aebf834cc Mon Sep 17 00:00:00 2001 From: Matej Vasek Date: Sun, 21 Feb 2021 19:33:05 +0100 Subject: [NO TESTS NEEDED] Make binding util internal The functions are supposed to be called only from generated code Signed-off-by: Matej Vasek --- pkg/bindings/internal/util/util.go | 102 +++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 pkg/bindings/internal/util/util.go (limited to 'pkg/bindings/internal') diff --git a/pkg/bindings/internal/util/util.go b/pkg/bindings/internal/util/util.go new file mode 100644 index 000000000..c1961308e --- /dev/null +++ b/pkg/bindings/internal/util/util.go @@ -0,0 +1,102 @@ +package util + +import ( + "errors" + "fmt" + "net/url" + "reflect" + "strconv" + "strings" + + jsoniter "github.com/json-iterator/go" +) + +func IsSimpleType(f reflect.Value) bool { + if _, ok := f.Interface().(fmt.Stringer); ok { + return true + } + + switch f.Kind() { + case reflect.Bool, reflect.Int, reflect.Int64, reflect.Uint, reflect.Uint64, reflect.String: + return true + } + + return false +} + +func SimpleTypeToParam(f reflect.Value) string { + if s, ok := f.Interface().(fmt.Stringer); ok { + return s.String() + } + + switch f.Kind() { + case reflect.Bool: + return strconv.FormatBool(f.Bool()) + case reflect.Int, reflect.Int64: + // f.Int() is always an int64 + return strconv.FormatInt(f.Int(), 10) + case reflect.Uint, reflect.Uint64: + // f.Uint() is always an uint64 + return strconv.FormatUint(f.Uint(), 10) + case reflect.String: + return f.String() + } + + panic("the input parameter is not a simple type") +} + +func Changed(o interface{}, fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +func ToParams(o interface{}) (url.Values, error) { + params := url.Values{} + if o == nil || reflect.ValueOf(o).IsNil() { + return params, nil + } + json := jsoniter.ConfigCompatibleWithStandardLibrary + s := reflect.ValueOf(o) + if reflect.Ptr == s.Kind() { + s = s.Elem() + } + sType := s.Type() + for i := 0; i < s.NumField(); i++ { + fieldName := sType.Field(i).Name + if !Changed(o, fieldName) { + continue + } + fieldName = strings.ToLower(fieldName) + f := s.Field(i) + if reflect.Ptr == f.Kind() { + f = f.Elem() + } + switch { + case IsSimpleType(f): + params.Set(fieldName, SimpleTypeToParam(f)) + case f.Kind() == reflect.Slice: + for i := 0; i < f.Len(); i++ { + elem := f.Index(i) + if IsSimpleType(elem) { + params.Add(fieldName, SimpleTypeToParam(elem)) + } else { + return nil, errors.New("slices must contain only simple types") + } + } + case f.Kind() == reflect.Map: + lowerCaseKeys := make(map[string][]string) + iter := f.MapRange() + for iter.Next() { + lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface().([]string) + } + s, err := json.MarshalToString(lowerCaseKeys) + if err != nil { + return nil, err + } + + params.Set(fieldName, s) + } + } + return params, nil +} -- cgit v1.2.3-54-g00ecf