github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/proto/generic/utils.go (about) 1 package generic 2 3 import ( 4 "reflect" 5 "strconv" 6 "strings" 7 "testing" 8 9 "github.com/cloudwego/dynamicgo/proto" 10 "github.com/stretchr/testify/require" 11 ) 12 13 var bytesType = reflect.TypeOf([]byte{}) 14 15 const ( 16 none int = 0 17 b2s int = 1 18 s2b int = 2 19 ) 20 21 func toInterface(v interface{}) interface{} { 22 return toInterface2(v, false, none) 23 } 24 25 func toInterface2(v interface{}, fieldId bool, byte2string int) interface{} { 26 vt := reflect.ValueOf(v) 27 if vt.Kind() == reflect.Ptr { 28 if vt.IsNil() { 29 return nil 30 } 31 vt = vt.Elem() 32 } 33 if k := vt.Kind(); k == reflect.Slice || k == reflect.Array { 34 if vt.Type() == bytesType { 35 if byte2string == b2s { 36 return string(vt.Bytes()) 37 } else { 38 return vt.Bytes() 39 } 40 } 41 var r = make([]interface{}, 0, vt.Len()) 42 for i := 0; i < vt.Len(); i++ { 43 vv := toInterface2(vt.Index(i).Interface(), fieldId, byte2string) 44 if vv != nil { 45 r = append(r, vv) 46 } 47 } 48 return r 49 } else if k == reflect.Map { 50 if kt := vt.Type().Key().Kind(); kt == reflect.String { 51 var r = make(map[string]interface{}, vt.Len()) 52 for _, k := range vt.MapKeys() { 53 vv := toInterface2(vt.MapIndex(k).Interface(), fieldId, byte2string) 54 if vv != nil { 55 r[k.String()] = vv 56 } 57 } 58 return r 59 } else if kt == reflect.Int || kt == reflect.Int8 || kt == reflect.Int16 || kt == reflect.Int32 || kt == reflect.Int64 { 60 var r = make(map[int]interface{}, vt.Len()) 61 for _, k := range vt.MapKeys() { 62 vv := toInterface2(vt.MapIndex(k).Interface(), fieldId, byte2string) 63 if vv != nil { 64 r[int(k.Int())] = vv 65 } 66 } 67 return r 68 } else { 69 var r = make(map[interface{}]interface{}, vt.Len()) 70 for _, k := range vt.MapKeys() { 71 kv := toInterface2(k.Interface(), fieldId, byte2string) 72 vv := toInterface2(vt.MapIndex(k).Interface(), fieldId, byte2string) 73 if kv != nil && vv != nil { 74 switch t := kv.(type) { 75 case map[string]interface{}: 76 r[&t] = vv 77 case map[int]interface{}: 78 r[&t] = vv 79 case map[interface{}]interface{}: 80 r[&t] = vv 81 case []interface{}: 82 r[&t] = vv 83 default: 84 r[kv] = vv 85 } 86 } 87 } 88 return r 89 } 90 } else if k == reflect.Struct { 91 var r interface{} 92 if fieldId { 93 r = map[proto.FieldNumber]interface{}{} 94 } else { 95 r = map[int]interface{}{} 96 } 97 for i := 0; i < vt.NumField(); i++ { 98 field := vt.Type().Field(i) 99 if field.Name == "state" || field.Name == "unknownFields" || field.Name == "sizeCache" { 100 continue 101 } 102 tag := field.Tag.Get("protobuf") 103 ts := strings.Split(tag, ",") 104 id := i 105 if len(ts) > 1 { 106 id, _ = strconv.Atoi(ts[1]) 107 } 108 vv := toInterface2(vt.Field(i).Interface(), fieldId, byte2string) 109 if vv != nil { 110 if fieldId { 111 r.(map[proto.FieldNumber]interface{})[proto.FieldNumber(id)] = vv 112 } else { 113 r.(map[int]interface{})[int(id)] = vv 114 } 115 } 116 } 117 return r 118 } else if k == reflect.Int || k == reflect.Int8 || k == reflect.Int16 || k == reflect.Int32 || k == reflect.Int64 { 119 return int(vt.Int()) 120 } else if k == reflect.String { 121 if byte2string == s2b { 122 return []byte(vt.String()) 123 } else { 124 return vt.String() 125 } 126 } 127 return vt.Interface() 128 } 129 130 func deepEqual(exp interface{}, act interface{}) bool { 131 switch ev := exp.(type) { 132 case map[int]interface{}: 133 av, ok := act.(map[int]interface{}) 134 if !ok { 135 return false 136 } 137 for k, v := range ev { 138 vv, ok := av[k] 139 if !ok { 140 return false 141 } 142 if !deepEqual(v, vv) { 143 return false 144 } 145 } 146 return true 147 case map[string]interface{}: 148 av, ok := act.(map[string]interface{}) 149 if !ok { 150 return false 151 } 152 for k, v := range ev { 153 vv, ok := av[k] 154 if !ok { 155 return false 156 } 157 if !deepEqual(v, vv) { 158 return false 159 } 160 } 161 return true 162 case map[interface{}]interface{}: 163 av, ok := act.(map[interface{}]interface{}) 164 if !ok { 165 return false 166 } 167 if len(ev) == 0 { 168 return true 169 } 170 erv := reflect.ValueOf(ev) 171 arv := reflect.ValueOf(av) 172 eks := erv.MapKeys() 173 aks := arv.MapKeys() 174 isPointer := eks[0].Elem().Kind() == reflect.Ptr 175 if !isPointer { 176 for k, v := range ev { 177 vv, ok := av[k] 178 if !ok { 179 return false 180 } 181 if !deepEqual(v, vv) { 182 return false 183 } 184 } 185 } else { 186 for _, ek := range eks { 187 found := false 188 for _, ak := range aks { 189 if deepEqual(ek.Elem().Elem().Interface(), ak.Elem().Elem().Interface()) { 190 found = true 191 evv := erv.MapIndex(ek) 192 avv := arv.MapIndex(ak) 193 if !deepEqual(evv.Interface(), avv.Interface()) { 194 return false 195 } 196 } 197 if !found { 198 return false 199 } 200 } 201 } 202 } 203 return true 204 case []interface{}: 205 av, ok := act.([]interface{}) 206 if !ok { 207 return false 208 } 209 for i, v := range ev { 210 vv := av[i] 211 if !deepEqual(v, vv) { 212 return false 213 } 214 } 215 return true 216 default: 217 return reflect.DeepEqual(exp, act) 218 } 219 } 220 221 func cast(ev interface{}, b bool) interface{} { 222 switch ev.(type) { 223 case int8: 224 if b { 225 return byte(ev.(int8)) 226 } 227 return int(ev.(int8)) 228 case int16: 229 return int(ev.(int16)) 230 case int32: 231 return int(ev.(int32)) 232 case int64: 233 return int(ev.(int64)) 234 case float32: 235 return float64(ev.(float32)) 236 default: 237 return ev 238 } 239 } 240 241 242 func checkHelper(t *testing.T, exp interface{}, act Value, api string) { 243 v := reflect.ValueOf(act) 244 f := v.MethodByName(api) 245 if f.Kind() != reflect.Func { 246 t.Fatalf("method %s not found", api) 247 } 248 var args []reflect.Value 249 if api == "List" || api == "StrMap" || api == "IntMap" || api == "Interface" { 250 args = make([]reflect.Value, 1) 251 args[0] = reflect.ValueOf(&Options{}) 252 } else { 253 args = make([]reflect.Value, 0) 254 } 255 rets := f.Call(args) 256 if len(rets) != 2 { 257 t.Fatal("wrong number of return values") 258 } 259 require.Nil(t, rets[1].Interface()) 260 switch api { 261 case "List": 262 vs := rets[0] 263 if vs.Kind() != reflect.Slice { 264 t.Fatal("wrong type") 265 } 266 es := reflect.ValueOf(exp) 267 if es.Kind() != reflect.Slice { 268 t.Fatal("wrong type") 269 } 270 for i := 0; i < vs.Len(); i++ { 271 vv := vs.Index(i) 272 require.Equal(t, cast(es.Index(i).Interface(), vv.Type().Name() == "byte"), vv.Interface()) 273 } 274 case "StrMap": 275 vs := rets[0] 276 if vs.Kind() != reflect.Map { 277 t.Fatal("wrong type") 278 } 279 es := reflect.ValueOf(exp) 280 if es.Kind() != reflect.Map { 281 t.Fatal("wrong type") 282 } 283 ks := vs.MapKeys() 284 for i := 0; i < len(ks); i++ { 285 vv := vs.MapIndex(ks[i]) 286 require.Equal(t, cast(es.MapIndex(ks[i]).Interface(), vv.Type().Name() == "byte"), vv.Interface()) 287 } 288 default: 289 require.Equal(t, exp, rets[0].Interface()) 290 } 291 } 292 293 func testDeepEqual(t *testing.T) { 294 a := map[interface{}]interface{}{ 295 float64(0.1): "A", 296 float64(0.2): "B", 297 float64(0.3): "C", 298 float64(0.4): "D", 299 float64(0.5): "E", 300 float64(0.6): "F", 301 float64(0.7): "G", 302 float64(0.8): "H", 303 float64(0.9): "I", 304 } 305 b := map[interface{}]interface{}{ 306 float64(0.4): "D", 307 float64(0.8): "H", 308 float64(0.7): "G", 309 float64(0.5): "E", 310 float64(0.6): "F", 311 float64(0.9): "I", 312 float64(0.2): "B", 313 float64(0.1): "A", 314 float64(0.3): "C", 315 } 316 for i := 0; i < 10; i++ { 317 require.Equal(t, a, b) 318 } 319 require.True(t, deepEqual(a, b)) 320 } 321 322 func structToMapStringInterface(data interface{}) map[string]interface{} { 323 result := make(map[string]interface{}) 324 valueType := reflect.TypeOf(data) 325 value := reflect.ValueOf(data) 326 327 for i := 0; i < valueType.NumField(); i++ { 328 field := valueType.Field(i) 329 fieldName := field.Name 330 if fieldName == "state" || fieldName == "unknownFields" || fieldName == "sizeCache" { 331 continue 332 } 333 fieldValue := value.FieldByName(fieldName).Interface() 334 result[fieldName] = fieldValue 335 } 336 337 return result 338 } 339 340 341 func structToMapFieldNumberInterface(data interface{}, desc *proto.MessageDescriptor) map[proto.FieldNumber]interface{} { 342 result := make(map[proto.FieldNumber]interface{}) 343 valueType := reflect.TypeOf(data) 344 value := reflect.ValueOf(data) 345 346 for i := 0; i < valueType.NumField(); i++ { 347 field := valueType.Field(i) 348 fieldName := field.Name 349 if fieldName == "state" || fieldName == "unknownFields" || fieldName == "sizeCache" { 350 continue 351 } 352 fieldValue := value.FieldByName(fieldName).Interface() 353 354 // Convert the field name to FieldNumber type 355 fieldNumber := desc.ByName(fieldName).Number() 356 357 result[fieldNumber] = fieldValue 358 } 359 360 return result 361 } 362 363 364 365 366 367 368