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  }