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