github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/generic/cast_test.go (about) 1 /** 2 * Copyright 2023 CloudWeGo Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package generic 18 19 import ( 20 "fmt" 21 "reflect" 22 "strconv" 23 "strings" 24 "testing" 25 26 "github.com/cloudwego/dynamicgo/meta" 27 "github.com/cloudwego/dynamicgo/testdata/sample" 28 "github.com/cloudwego/dynamicgo/thrift" 29 "github.com/stretchr/testify/require" 30 ) 31 32 var ( 33 PathInnerBase = NewPathFieldName("InnerBase") 34 PathNotExist = []Path{NewPathFieldName("NotExist")} 35 PathExampleBool = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(1))} 36 PathExampleByte = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(2))} 37 PathExampleInt16 = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(3))} 38 PathExampleInt32 = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(4))} 39 PathExampleInt64 = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(5))} 40 PathExampleDouble = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(6))} 41 PathExampleString = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(7))} 42 PathExampleListInt32 = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(8))} 43 PathExampleMapStringString = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(9))} 44 PathExampleSetInt32_ = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(10))} 45 PathExampleFoo = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(11))} 46 PathExampleMapInt32String = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(12))} 47 PathExampleBinary = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(13))} 48 PathExampleBase = []Path{PathInnerBase, NewPathFieldId(thrift.FieldID(255))} 49 ) 50 51 func TestCastInt8(t *testing.T) { 52 var exp = byte(129) 53 var n = NewNodeByte(exp) 54 act, err := n.Int() 55 require.Nil(t, err) 56 require.Equal(t, int(exp), act) 57 } 58 59 func TestCastAPI(t *testing.T) { 60 desc := getExampleDesc() 61 data := getExampleData() 62 var errUnsupportedType = errNode(meta.ErrUnsupportedType, "", nil) 63 var errNotFound = errNode(meta.ErrUnknownField, "", nil) 64 // var errInvalidParam = errNode(meta.ErrInvalidParam, "", nil) 65 var opts = &Options{} 66 cases := []testAPICase{ 67 {path: PathNotExist, api: "Bool", exp: false, err: errNotFound}, 68 {path: PathNotExist, api: "Byte", exp: byte(0), err: errNotFound}, 69 {path: PathNotExist, api: "Int", exp: int(0), err: errNotFound}, 70 {path: PathNotExist, api: "Float64", exp: float64(0), err: errNotFound}, 71 {path: PathNotExist, api: "String", exp: "", err: errNotFound}, 72 {path: PathNotExist, api: "Binary", exp: []byte(nil), err: errNotFound}, 73 {path: PathNotExist, api: "List", exp: []interface{}(nil), err: errNotFound, args: []interface{}{opts}}, 74 {path: PathNotExist, api: "StrMap", exp: map[string]interface{}(nil), err: errNotFound, args: []interface{}{opts}}, 75 {path: PathNotExist, api: "IntMap", exp: map[int]interface{}(nil), err: errNotFound, args: []interface{}{opts}}, 76 {path: PathNotExist, api: "Interface", exp: nil, err: errNotFound, args: []interface{}{opts}}, 77 78 {path: PathExampleBool, api: "Bool", exp: sample.Example2Obj.InnerBase.Bool}, 79 {path: PathExampleBool, api: "Byte", exp: byte(0), err: errUnsupportedType}, 80 {path: PathExampleBool, api: "Int", exp: int(0), err: errUnsupportedType}, 81 {path: PathExampleBool, api: "Float64", exp: float64(0), err: errUnsupportedType}, 82 {path: PathExampleBool, api: "String", exp: "", err: errUnsupportedType}, 83 {path: PathExampleBool, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 84 {path: PathExampleBool, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 85 {path: PathExampleBool, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 86 {path: PathExampleBool, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 87 {path: PathExampleBool, api: "Interface", exp: sample.Example2Obj.InnerBase.Bool, args: []interface{}{opts}}, 88 89 {path: PathExampleByte, api: "Bool", exp: false, err: errUnsupportedType}, 90 {path: PathExampleByte, api: "Byte", exp: byte(sample.Example2Obj.InnerBase.Byte)}, 91 {path: PathExampleByte, api: "Int", exp: int(sample.Example2Obj.InnerBase.Byte)}, 92 {path: PathExampleByte, api: "Float64", exp: float64(0), err: errUnsupportedType}, 93 {path: PathExampleByte, api: "String", exp: "", err: errUnsupportedType}, 94 {path: PathExampleByte, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 95 {path: PathExampleByte, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 96 {path: PathExampleByte, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 97 {path: PathExampleByte, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 98 {path: PathExampleByte, api: "Interface", exp: int(sample.Example2Obj.InnerBase.Byte), args: []interface{}{opts}}, 99 100 {path: PathExampleInt16, api: "Bool", exp: false, err: errUnsupportedType}, 101 {path: PathExampleInt16, api: "Byte", exp: byte(0), err: errUnsupportedType}, 102 {path: PathExampleInt16, api: "Int", exp: int(sample.Example2Obj.InnerBase.Int16)}, 103 {path: PathExampleInt16, api: "Float64", exp: float64(0), err: errUnsupportedType}, 104 {path: PathExampleInt16, api: "String", exp: "", err: errUnsupportedType}, 105 {path: PathExampleInt16, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 106 {path: PathExampleInt16, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 107 {path: PathExampleInt16, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 108 {path: PathExampleInt16, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 109 {path: PathExampleInt16, api: "Interface", exp: int(sample.Example2Obj.InnerBase.Int16), args: []interface{}{opts}}, 110 111 {path: PathExampleInt32, api: "Bool", exp: false, err: errUnsupportedType}, 112 {path: PathExampleInt32, api: "Byte", exp: byte(0), err: errUnsupportedType}, 113 {path: PathExampleInt32, api: "Int", exp: int(sample.Example2Obj.InnerBase.Int32)}, 114 {path: PathExampleInt32, api: "Float64", exp: float64(0), err: errUnsupportedType}, 115 {path: PathExampleInt32, api: "String", exp: "", err: errUnsupportedType}, 116 {path: PathExampleInt32, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 117 {path: PathExampleInt32, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 118 {path: PathExampleInt32, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 119 {path: PathExampleInt32, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 120 {path: PathExampleInt32, api: "Interface", exp: int(sample.Example2Obj.InnerBase.Int32), args: []interface{}{opts}}, 121 122 {path: PathExampleInt64, api: "Bool", exp: false, err: errUnsupportedType}, 123 {path: PathExampleInt64, api: "Byte", exp: byte(0), err: errUnsupportedType}, 124 {path: PathExampleInt64, api: "Int", exp: int(sample.Example2Obj.InnerBase.Int64)}, 125 {path: PathExampleInt64, api: "Float64", exp: float64(0), err: errUnsupportedType}, 126 {path: PathExampleInt64, api: "String", exp: "", err: errUnsupportedType}, 127 {path: PathExampleInt64, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 128 {path: PathExampleInt64, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 129 {path: PathExampleInt64, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 130 {path: PathExampleInt64, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 131 {path: PathExampleInt64, api: "Interface", exp: int(sample.Example2Obj.InnerBase.Int64), args: []interface{}{opts}}, 132 133 {path: PathExampleDouble, api: "Bool", exp: false, err: errUnsupportedType}, 134 {path: PathExampleDouble, api: "Byte", exp: byte(0), err: errUnsupportedType}, 135 {path: PathExampleDouble, api: "Int", exp: int(0), err: errUnsupportedType}, 136 {path: PathExampleDouble, api: "Float64", exp: sample.Example2Obj.InnerBase.Double}, 137 {path: PathExampleDouble, api: "String", exp: "", err: errUnsupportedType}, 138 {path: PathExampleDouble, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 139 {path: PathExampleDouble, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 140 {path: PathExampleDouble, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 141 {path: PathExampleDouble, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 142 {path: PathExampleDouble, api: "Interface", exp: float64(sample.Example2Obj.InnerBase.Double), args: []interface{}{opts}}, 143 144 {path: PathExampleString, api: "Bool", exp: false, err: errUnsupportedType}, 145 {path: PathExampleString, api: "Byte", exp: byte(0), err: errUnsupportedType}, 146 {path: PathExampleString, api: "Int", exp: int(0), err: errUnsupportedType}, 147 {path: PathExampleString, api: "Float64", exp: float64(0), err: errUnsupportedType}, 148 {path: PathExampleString, api: "String", exp: sample.Example2Obj.InnerBase.String_}, 149 {path: PathExampleString, api: "Binary", exp: []byte(sample.Example2Obj.InnerBase.String_)}, 150 {path: PathExampleString, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 151 {path: PathExampleString, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 152 {path: PathExampleString, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 153 {path: PathExampleString, api: "Interface", exp: string(sample.Example2Obj.InnerBase.String_), args: []interface{}{opts}}, 154 155 {path: PathExampleBinary, api: "Bool", exp: false, err: errUnsupportedType}, 156 {path: PathExampleBinary, api: "Byte", exp: byte(0), err: errUnsupportedType}, 157 {path: PathExampleBinary, api: "Int", exp: int(0), err: errUnsupportedType}, 158 {path: PathExampleBinary, api: "Float64", exp: float64(0), err: errUnsupportedType}, 159 {path: PathExampleBinary, api: "String", exp: string(sample.Example2Obj.InnerBase.Binary)}, 160 {path: PathExampleBinary, api: "Binary", exp: []byte(sample.Example2Obj.InnerBase.Binary)}, 161 {path: PathExampleBinary, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 162 {path: PathExampleBinary, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 163 {path: PathExampleBinary, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 164 {path: PathExampleBinary, api: "Interface", exp: string(sample.Example2Obj.InnerBase.Binary), args: []interface{}{opts}}, 165 166 {path: PathExampleFoo, api: "Bool", exp: false, err: errUnsupportedType}, 167 {path: PathExampleFoo, api: "Byte", exp: byte(0), err: errUnsupportedType}, 168 {path: PathExampleFoo, api: "Int", exp: int(sample.Example2Obj.InnerBase.Foo)}, 169 {path: PathExampleFoo, api: "Float64", exp: float64(0), err: errUnsupportedType}, 170 {path: PathExampleFoo, api: "String", exp: "", err: errUnsupportedType}, 171 {path: PathExampleFoo, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 172 {path: PathExampleFoo, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 173 {path: PathExampleFoo, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 174 {path: PathExampleFoo, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 175 {path: PathExampleFoo, api: "Interface", exp: int(sample.Example2Obj.InnerBase.Foo), args: []interface{}{opts}}, 176 177 {path: PathExampleListInt32, api: "Bool", exp: false, err: errUnsupportedType}, 178 {path: PathExampleListInt32, api: "Byte", exp: byte(0), err: errUnsupportedType}, 179 {path: PathExampleListInt32, api: "Int", exp: int(0), err: errUnsupportedType}, 180 {path: PathExampleListInt32, api: "Float64", exp: float64(0), err: errUnsupportedType}, 181 {path: PathExampleListInt32, api: "String", exp: "", err: errUnsupportedType}, 182 {path: PathExampleListInt32, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 183 {path: PathExampleListInt32, api: "List", exp: toInterface(sample.Example2Obj.InnerBase.ListInt32), args: []interface{}{opts}}, 184 {path: PathExampleListInt32, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 185 {path: PathExampleListInt32, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 186 {path: PathExampleListInt32, api: "Interface", exp: toInterface(sample.Example2Obj.InnerBase.ListInt32), args: []interface{}{opts}}, 187 188 {path: PathExampleSetInt32_, api: "Bool", exp: false, err: errUnsupportedType}, 189 {path: PathExampleSetInt32_, api: "Byte", exp: byte(0), err: errUnsupportedType}, 190 {path: PathExampleSetInt32_, api: "Int", exp: int(0), err: errUnsupportedType}, 191 {path: PathExampleSetInt32_, api: "Float64", exp: float64(0), err: errUnsupportedType}, 192 {path: PathExampleSetInt32_, api: "String", exp: "", err: errUnsupportedType}, 193 {path: PathExampleSetInt32_, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 194 {path: PathExampleSetInt32_, api: "List", exp: toInterface(sample.Example2Obj.InnerBase.ListInt32), args: []interface{}{opts}}, 195 {path: PathExampleSetInt32_, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 196 {path: PathExampleSetInt32_, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 197 {path: PathExampleSetInt32_, api: "Interface", exp: toInterface(sample.Example2Obj.InnerBase.ListInt32), args: []interface{}{opts}}, 198 199 {path: PathExampleMapInt32String, api: "Bool", exp: false, err: errUnsupportedType}, 200 {path: PathExampleMapInt32String, api: "Byte", exp: byte(0), err: errUnsupportedType}, 201 {path: PathExampleMapInt32String, api: "Int", exp: int(0), err: errUnsupportedType}, 202 {path: PathExampleMapInt32String, api: "Float64", exp: float64(0), err: errUnsupportedType}, 203 {path: PathExampleMapInt32String, api: "String", exp: "", err: errUnsupportedType}, 204 {path: PathExampleMapInt32String, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 205 {path: PathExampleMapInt32String, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 206 {path: PathExampleMapInt32String, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 207 {path: PathExampleMapInt32String, api: "IntMap", exp: toInterface(sample.Example2Obj.InnerBase.MapInt32String), args: []interface{}{opts}}, 208 {path: PathExampleMapInt32String, api: "Interface", exp: toInterface(sample.Example2Obj.InnerBase.MapInt32String), args: []interface{}{opts}}, 209 210 {path: PathExampleMapStringString, api: "Bool", exp: false, err: errUnsupportedType}, 211 {path: PathExampleMapStringString, api: "Byte", exp: byte(0), err: errUnsupportedType}, 212 {path: PathExampleMapStringString, api: "Int", exp: int(0), err: errUnsupportedType}, 213 {path: PathExampleMapStringString, api: "Float64", exp: float64(0), err: errUnsupportedType}, 214 {path: PathExampleMapStringString, api: "String", exp: "", err: errUnsupportedType}, 215 {path: PathExampleMapStringString, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 216 {path: PathExampleMapStringString, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 217 {path: PathExampleMapStringString, api: "StrMap", exp: toInterface(sample.Example2Obj.InnerBase.MapStringString), args: []interface{}{opts}}, 218 {path: PathExampleMapStringString, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 219 {path: PathExampleMapStringString, api: "Interface", exp: toInterface(sample.Example2Obj.InnerBase.MapStringString), args: []interface{}{opts}}, 220 {path: PathExampleMapStringString, api: "Interface", exp: toInterface2(sample.Example2Obj.InnerBase.MapStringString, false, 2), args: []interface{}{&Options{ 221 CastStringAsBinary: true, 222 }}}, 223 224 {path: PathExampleBase, api: "Bool", exp: false, err: errUnsupportedType}, 225 {path: PathExampleBase, api: "Byte", exp: byte(0), err: errUnsupportedType}, 226 {path: PathExampleBase, api: "Int", exp: int(0), err: errUnsupportedType}, 227 {path: PathExampleBase, api: "Float64", exp: float64(0), err: errUnsupportedType}, 228 {path: PathExampleBase, api: "String", exp: "", err: errUnsupportedType}, 229 {path: PathExampleBase, api: "Binary", exp: []byte(nil), err: errUnsupportedType}, 230 {path: PathExampleBase, api: "List", exp: []interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 231 {path: PathExampleBase, api: "StrMap", exp: map[string]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 232 {path: PathExampleBase, api: "IntMap", exp: map[int]interface{}(nil), err: errUnsupportedType, args: []interface{}{opts}}, 233 {path: PathExampleBase, api: "Interface", exp: toInterface2(sample.Example2Obj.InnerBase.Base, false, 0), args: []interface{}{opts}}, 234 {path: PathExampleBase, api: "Interface", exp: toInterface2(sample.Example2Obj.InnerBase.Base, true, 0), args: []interface{}{&Options{ 235 MapStructById: true, 236 }}}, 237 } 238 root := NewValue(desc, data) 239 for _, c := range cases { 240 t.Run(fmt.Sprintf(c.path[len(c.path)-1].String())+c.api, func(t *testing.T) { 241 APIHelper(t, &root, nil, c) 242 }) 243 } 244 } 245 246 type testAPICase struct { 247 name string 248 path []Path 249 api string 250 args []interface{} 251 exp interface{} 252 err error 253 strictErr bool 254 } 255 256 func APIHelper(t *testing.T, root *Value, val *Value, c testAPICase) { 257 if val == nil { 258 t := root.GetByPath(c.path...) 259 val = &t 260 } 261 // require.Nil(t, val.Check()) 262 vt := reflect.ValueOf(val) 263 mt := vt.MethodByName(c.api) 264 265 var args []reflect.Value 266 if len(c.args) > 0 { 267 args = make([]reflect.Value, len(c.args)) 268 for i, arg := range c.args { 269 args[i] = reflect.ValueOf(arg) 270 } 271 } 272 273 rs := mt.Call(args) 274 var e interface{} 275 if len(rs) == 2 { 276 e = rs[1].Interface() 277 } else { 278 e = rs[0].Interface() 279 } 280 281 require.Equal(t, c.err == nil, e == nil) 282 if e != nil { 283 if n, ok := c.err.(Value); ok { 284 n2, ok2 := e.(Value) 285 if !ok2 { 286 n3, ok3 := e.(Node) 287 if !ok3 { 288 t.Fatal("not a node erro ") 289 } else { 290 require.Equal(t, n.ErrCode(), n3.ErrCode()) 291 } 292 } 293 require.Equal(t, n.ErrCode(), n2.ErrCode()) 294 } else if nn, ok := c.err.(meta.Error); ok { 295 nn2, ok2 := e.(meta.Error) 296 if !ok2 { 297 n3, ok3 := e.(Node) 298 if !ok3 { 299 t.Fatal("not a node erro ") 300 } else { 301 require.Equal(t, nn.Code.Behavior(), n3.ErrCode().Behavior()) 302 } 303 } else { 304 require.True(t, ok2) 305 require.Equal(t, nn.Code.Behavior(), nn2.Code.Behavior()) 306 } 307 } 308 if c.strictErr { 309 require.Equal(t, c.err, e.(error)) 310 } 311 } 312 if len(rs) >= 2 { 313 require.Equal(t, c.exp, rs[0].Interface()) 314 } 315 } 316 317 func toInterface(v interface{}) interface{} { 318 return toInterface2(v, false, none) 319 } 320 321 var bytesType = reflect.TypeOf([]byte{}) 322 323 const ( 324 none int = 0 325 b2s int = 1 326 s2b int = 2 327 ) 328 329 func toInterface2(v interface{}, fieldId bool, byte2string int) interface{} { 330 vt := reflect.ValueOf(v) 331 if vt.Kind() == reflect.Ptr { 332 if vt.IsNil() { 333 return nil 334 } 335 vt = vt.Elem() 336 } 337 if k := vt.Kind(); k == reflect.Slice || k == reflect.Array { 338 if vt.Type() == bytesType { 339 if byte2string == b2s { 340 return string(vt.Bytes()) 341 } else { 342 return vt.Bytes() 343 } 344 } 345 var r = make([]interface{}, 0, vt.Len()) 346 for i := 0; i < vt.Len(); i++ { 347 vv := toInterface2(vt.Index(i).Interface(), fieldId, byte2string) 348 if vv != nil { 349 r = append(r, vv) 350 } 351 } 352 return r 353 } else if k == reflect.Map { 354 if kt := vt.Type().Key().Kind(); kt == reflect.String { 355 var r = make(map[string]interface{}, vt.Len()) 356 for _, k := range vt.MapKeys() { 357 vv := toInterface2(vt.MapIndex(k).Interface(), fieldId, byte2string) 358 if vv != nil { 359 r[k.String()] = vv 360 } 361 } 362 return r 363 } else if kt == reflect.Int || kt == reflect.Int8 || kt == reflect.Int16 || kt == reflect.Int32 || kt == reflect.Int64 { 364 var r = make(map[int]interface{}, vt.Len()) 365 for _, k := range vt.MapKeys() { 366 vv := toInterface2(vt.MapIndex(k).Interface(), fieldId, byte2string) 367 if vv != nil { 368 r[int(k.Int())] = vv 369 } 370 } 371 return r 372 } else { 373 var r = make(map[interface{}]interface{}, vt.Len()) 374 for _, k := range vt.MapKeys() { 375 kv := toInterface2(k.Interface(), fieldId, byte2string) 376 vv := toInterface2(vt.MapIndex(k).Interface(), fieldId, byte2string) 377 if kv != nil && vv != nil { 378 switch t := kv.(type) { 379 case map[string]interface{}: 380 r[&t] = vv 381 case map[int]interface{}: 382 r[&t] = vv 383 case map[interface{}]interface{}: 384 r[&t] = vv 385 case []interface{}: 386 r[&t] = vv 387 default: 388 r[kv] = vv 389 } 390 } 391 } 392 return r 393 } 394 } else if k == reflect.Struct { 395 var r interface{} 396 if fieldId { 397 r = map[thrift.FieldID]interface{}{} 398 } else { 399 r = map[int]interface{}{} 400 } 401 for i := 0; i < vt.NumField(); i++ { 402 field := vt.Type().Field(i) 403 tag := field.Tag.Get("thrift") 404 ts := strings.Split(tag, ",") 405 id := i 406 if len(ts) > 1 { 407 id, _ = strconv.Atoi(ts[1]) 408 } 409 vv := toInterface2(vt.Field(i).Interface(), fieldId, byte2string) 410 if vv != nil { 411 if fieldId { 412 r.(map[thrift.FieldID]interface{})[thrift.FieldID(id)] = vv 413 } else { 414 r.(map[int]interface{})[int(id)] = vv 415 } 416 } 417 } 418 return r 419 } else if k == reflect.Int || k == reflect.Int8 || k == reflect.Int16 || k == reflect.Int32 || k == reflect.Int64 { 420 return int(vt.Int()) 421 } else if k == reflect.String { 422 if byte2string == s2b { 423 return []byte(vt.String()) 424 } else { 425 return vt.String() 426 } 427 } 428 return vt.Interface() 429 } 430 431 func specialFieldName(name string) string { 432 if len(name) > 0 && name[len(name)-1] == '_' { 433 return name[:len(name)-1] 434 } 435 return name 436 }