github.com/kubeshop/testkube@v1.17.23/pkg/tcl/expressionstcl/convert.go (about) 1 // Copyright 2024 Testkube. 2 // 3 // Licensed as a Testkube Pro file under the Testkube Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt 8 9 package expressionstcl 10 11 import ( 12 "encoding/json" 13 "fmt" 14 "reflect" 15 "strconv" 16 "strings" 17 ) 18 19 func toString(s interface{}) (string, error) { 20 // Fast track 21 v, ok := s.(string) 22 if ok { 23 return v, nil 24 } 25 if isNone(s) { 26 return "", nil 27 } 28 // Convert 29 if isNumber(s) { 30 return fmt.Sprintf("%v", s), nil 31 } 32 if isSlice(s) { 33 var err error 34 value := reflect.ValueOf(s) 35 results := make([]string, value.Len()) 36 for i := 0; i < value.Len(); i++ { 37 results[i], err = toString(value.Index(i).Interface()) 38 if err != nil { 39 err = fmt.Errorf("error while converting '%v' slice item: %v", value.Index(i), err) 40 return "", err 41 } 42 } 43 return strings.Join(results, ","), nil 44 } 45 b, err := json.Marshal(s) 46 if err != nil { 47 return "", fmt.Errorf("error while converting '%v' map to JSON: %v", s, err) 48 } 49 r := string(b) 50 if isMap(s) && r == "null" { 51 return "{}", nil 52 } 53 return r, nil 54 } 55 56 func toFloat(s interface{}) (float64, error) { 57 // Fast track 58 if v, ok := s.(float64); ok { 59 return v, nil 60 } 61 if isNone(s) { 62 return 0, nil 63 } 64 // Convert 65 str, err := toString(s) 66 if err != nil { 67 return 0, err 68 } 69 v, err := strconv.ParseFloat(str, 64) 70 if err != nil { 71 return 0, fmt.Errorf("error while converting value to number: %v: %v", s, err) 72 } 73 return v, nil 74 } 75 76 func toInt(s interface{}) (int64, error) { 77 // Fast track 78 if v, ok := s.(int64); ok { 79 return v, nil 80 } 81 if v, ok := s.(int); ok { 82 return int64(v), nil 83 } 84 if isNone(s) { 85 return 0, nil 86 } 87 // Convert 88 v, err := toFloat(s) 89 return int64(v), err 90 } 91 92 func toBool(s interface{}) (bool, error) { 93 // Fast track 94 if v, ok := s.(bool); ok { 95 return v, nil 96 } 97 if isNone(s) { 98 return false, nil 99 } 100 if isMap(s) || isSlice(s) { 101 return reflect.ValueOf(s).Len() > 0, nil 102 } 103 // Convert 104 value, err := toString(s) 105 if err != nil { 106 return false, fmt.Errorf("error while converting value to bool: %v: %v", value, err) 107 } 108 return !(value == "" || value == "false" || value == "0" || value == "off"), nil 109 } 110 111 func toMap(s interface{}) (map[string]interface{}, error) { 112 // Fast track 113 if v, ok := s.(map[string]interface{}); ok { 114 return v, nil 115 } 116 if isNone(s) { 117 return nil, nil 118 } 119 // Convert 120 if isStruct(s) { 121 v, err := json.Marshal(s) 122 if err != nil { 123 return nil, fmt.Errorf("error while marshaling value: %v: %v", s, err) 124 } 125 err = json.Unmarshal(v, &s) 126 if err != nil { 127 return nil, fmt.Errorf("error while unmarshaling value: %v: %v", s, err) 128 } 129 } 130 if isMap(s) { 131 value := reflect.ValueOf(s) 132 res := make(map[string]interface{}, value.Len()) 133 for _, k := range value.MapKeys() { 134 kk, err := toString(k.Interface()) 135 if err != nil { 136 return nil, fmt.Errorf("error while converting map key to string: %v: %v", k, err) 137 } 138 res[kk] = value.MapIndex(k).Interface() 139 } 140 return res, nil 141 } 142 if isSlice(s) { 143 value := reflect.ValueOf(s) 144 res := make(map[string]interface{}, value.Len()) 145 for i := 0; i < value.Len(); i++ { 146 res[strconv.Itoa(i)] = value.Index(i).Interface() 147 } 148 return res, nil 149 } 150 return nil, fmt.Errorf("error while converting value to map: %v", s) 151 } 152 153 func toSlice(s interface{}) ([]interface{}, error) { 154 // Fast track 155 if v, ok := s.([]interface{}); ok { 156 return v, nil 157 } 158 if isNone(s) { 159 return nil, nil 160 } 161 // Convert 162 if isSlice(s) { 163 value := reflect.ValueOf(s) 164 res := make([]interface{}, value.Len()) 165 for i := 0; i < value.Len(); i++ { 166 res[i] = value.Index(i).Interface() 167 } 168 return res, nil 169 } 170 if isMap(s) { 171 return nil, fmt.Errorf("error while converting map to slice: %v", s) 172 } 173 return nil, fmt.Errorf("error while converting value to slice: %v", s) 174 }