...

Source file src/github.com/jackc/pgx/v5/pgtype/convert.go

Documentation: github.com/jackc/pgx/v5/pgtype

     1  package pgtype
     2  
     3  import (
     4  	"reflect"
     5  )
     6  
     7  func NullAssignTo(dst any) error {
     8  	dstPtr := reflect.ValueOf(dst)
     9  
    10  	// AssignTo dst must always be a pointer
    11  	if dstPtr.Kind() != reflect.Ptr {
    12  		return &nullAssignmentError{dst: dst}
    13  	}
    14  
    15  	dstVal := dstPtr.Elem()
    16  
    17  	switch dstVal.Kind() {
    18  	case reflect.Ptr, reflect.Slice, reflect.Map:
    19  		dstVal.Set(reflect.Zero(dstVal.Type()))
    20  		return nil
    21  	}
    22  
    23  	return &nullAssignmentError{dst: dst}
    24  }
    25  
    26  var kindTypes map[reflect.Kind]reflect.Type
    27  
    28  func toInterface(dst reflect.Value, t reflect.Type) (any, bool) {
    29  	nextDst := dst.Convert(t)
    30  	return nextDst.Interface(), dst.Type() != nextDst.Type()
    31  }
    32  
    33  // GetAssignToDstType attempts to convert dst to something AssignTo can assign
    34  // to. If dst is a pointer to pointer it allocates a value and returns the
    35  // dereferences pointer. If dst is a named type such as *Foo where Foo is type
    36  // Foo int16, it converts dst to *int16.
    37  //
    38  // GetAssignToDstType returns the converted dst and a bool representing if any
    39  // change was made.
    40  func GetAssignToDstType(dst any) (any, bool) {
    41  	dstPtr := reflect.ValueOf(dst)
    42  
    43  	// AssignTo dst must always be a pointer
    44  	if dstPtr.Kind() != reflect.Ptr {
    45  		return nil, false
    46  	}
    47  
    48  	dstVal := dstPtr.Elem()
    49  
    50  	// if dst is a pointer to pointer, allocate space try again with the dereferenced pointer
    51  	if dstVal.Kind() == reflect.Ptr {
    52  		dstVal.Set(reflect.New(dstVal.Type().Elem()))
    53  		return dstVal.Interface(), true
    54  	}
    55  
    56  	// if dst is pointer to a base type that has been renamed
    57  	if baseValType, ok := kindTypes[dstVal.Kind()]; ok {
    58  		return toInterface(dstPtr, reflect.PtrTo(baseValType))
    59  	}
    60  
    61  	if dstVal.Kind() == reflect.Slice {
    62  		if baseElemType, ok := kindTypes[dstVal.Type().Elem().Kind()]; ok {
    63  			return toInterface(dstPtr, reflect.PtrTo(reflect.SliceOf(baseElemType)))
    64  		}
    65  	}
    66  
    67  	if dstVal.Kind() == reflect.Array {
    68  		if baseElemType, ok := kindTypes[dstVal.Type().Elem().Kind()]; ok {
    69  			return toInterface(dstPtr, reflect.PtrTo(reflect.ArrayOf(dstVal.Len(), baseElemType)))
    70  		}
    71  	}
    72  
    73  	if dstVal.Kind() == reflect.Struct {
    74  		if dstVal.Type().NumField() == 1 && dstVal.Type().Field(0).Anonymous {
    75  			dstPtr = dstVal.Field(0).Addr()
    76  			nested := dstVal.Type().Field(0).Type
    77  			if nested.Kind() == reflect.Array {
    78  				if baseElemType, ok := kindTypes[nested.Elem().Kind()]; ok {
    79  					return toInterface(dstPtr, reflect.PtrTo(reflect.ArrayOf(nested.Len(), baseElemType)))
    80  				}
    81  			}
    82  			if _, ok := kindTypes[nested.Kind()]; ok && dstPtr.CanInterface() {
    83  				return dstPtr.Interface(), true
    84  			}
    85  		}
    86  	}
    87  
    88  	return nil, false
    89  }
    90  
    91  func init() {
    92  	kindTypes = map[reflect.Kind]reflect.Type{
    93  		reflect.Bool:    reflect.TypeOf(false),
    94  		reflect.Float32: reflect.TypeOf(float32(0)),
    95  		reflect.Float64: reflect.TypeOf(float64(0)),
    96  		reflect.Int:     reflect.TypeOf(int(0)),
    97  		reflect.Int8:    reflect.TypeOf(int8(0)),
    98  		reflect.Int16:   reflect.TypeOf(int16(0)),
    99  		reflect.Int32:   reflect.TypeOf(int32(0)),
   100  		reflect.Int64:   reflect.TypeOf(int64(0)),
   101  		reflect.Uint:    reflect.TypeOf(uint(0)),
   102  		reflect.Uint8:   reflect.TypeOf(uint8(0)),
   103  		reflect.Uint16:  reflect.TypeOf(uint16(0)),
   104  		reflect.Uint32:  reflect.TypeOf(uint32(0)),
   105  		reflect.Uint64:  reflect.TypeOf(uint64(0)),
   106  		reflect.String:  reflect.TypeOf(""),
   107  	}
   108  }
   109  

View as plain text