github.com/blend/go-sdk@v1.20220411.3/db/reflection.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package db 9 10 import ( 11 "reflect" 12 ) 13 14 // ReflectValue returns the reflect.Value for an object following pointers. 15 func ReflectValue(obj interface{}) reflect.Value { 16 v := reflect.ValueOf(obj) 17 for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { 18 v = v.Elem() 19 } 20 return v 21 } 22 23 // ReflectType retruns the reflect.Type for an object following pointers. 24 func ReflectType(obj interface{}) reflect.Type { 25 t := reflect.TypeOf(obj) 26 for t.Kind() == reflect.Ptr || t.Kind() == reflect.Interface { 27 t = t.Elem() 28 } 29 30 return t 31 } 32 33 // ReflectSliceType returns the inner type of a slice following pointers. 34 func ReflectSliceType(collection interface{}) reflect.Type { 35 v := reflect.ValueOf(collection) 36 for v.Kind() == reflect.Ptr { 37 v = v.Elem() 38 } 39 if v.Len() == 0 { 40 t := v.Type() 41 for t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice { 42 t = t.Elem() 43 } 44 return t 45 } 46 v = v.Index(0) 47 for v.Kind() == reflect.Interface || v.Kind() == reflect.Ptr { 48 v = v.Elem() 49 } 50 return v.Type() 51 } 52 53 // makeNew creates a new object. 54 func makeNew(t reflect.Type) interface{} { 55 return reflect.New(t).Interface() 56 } 57 58 func makeSliceOfType(t reflect.Type) interface{} { 59 return reflect.New(reflect.SliceOf(t)).Interface() 60 } 61 62 // haveSameUnderlyingTypes returns if T and V are such that V is *T or V is **T etc. 63 // It handles the cases where we're assigning T = convert(**T) which can happen when we're setting up 64 // scan output array. 65 // Convert can smush T and **T together somehow. 66 func haveSameUnderlyingTypes(t, v reflect.Value) bool { 67 tt := t.Type() 68 tv := ReflectType(v) 69 return tv.AssignableTo(tt) || tv.ConvertibleTo(tt) 70 }