github.com/haraldrudell/parl@v0.4.176/preflect/predeclared-type.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  // Package preflect obtains underlying type using reflection
     7  package preflect
     8  
     9  import (
    10  	"reflect"
    11  	"strconv"
    12  	"strings"
    13  	"unsafe"
    14  )
    15  
    16  const (
    17  	Nil      = "nil"
    18  	kindInt  = "int"
    19  	kindUint = "uint"
    20  )
    21  
    22  // bitSize is a string containing the size of int: "(64)"
    23  var bitSize = "(" + strconv.Itoa(int(unsafe.Sizeof(0)*8)) + ")"
    24  
    25  // PredeclaredType returns a string describing the underlying type of value
    26  //   - examples: "bool" "uint8" "int(64)"
    27  //   - no named types or type aliases
    28  func PredeclaredType(value any) (s string) {
    29  	return reflectTypeString(reflect.TypeOf(value))
    30  }
    31  
    32  func reflectTypeString(typeOf reflect.Type) (s string) {
    33  	if typeOf == nil {
    34  		return Nil
    35  	}
    36  	var kindOf reflect.Kind = typeOf.Kind()
    37  	switch kindOf {
    38  	case reflect.Chan:
    39  		var chanDir reflect.ChanDir = typeOf.ChanDir()
    40  		return chanDir.String() + " " + reflectTypeString(typeOf.Elem())
    41  	case reflect.Map:
    42  		return "[" + reflectTypeString(typeOf.Key()) + "]" + reflectTypeString(typeOf.Elem())
    43  	case reflect.Interface:
    44  		return "interface " + reflectTypeString(typeOf.Elem())
    45  	case reflect.Func:
    46  		var sIn, sOut string
    47  		if in := typeOf.NumIn(); in != 0 {
    48  			sInList := make([]string, in)
    49  			for i := range sInList {
    50  				sInList[i] = reflectTypeString(typeOf.In(i))
    51  			}
    52  			sIn = "(" + strings.Join(sInList, ", ") + ")"
    53  		} else {
    54  			sIn = "()"
    55  		}
    56  		if out := typeOf.NumOut(); out != 0 {
    57  			sOutList := make([]string, out)
    58  			for i := range sOutList {
    59  				sOutList[i] = reflectTypeString(typeOf.Out(i))
    60  			}
    61  			sOut = " (" + strings.Join(sOutList, ", ") + ")"
    62  		}
    63  		return kindOf.String() + sIn + sOut
    64  	case reflect.Ptr:
    65  		return "*" + reflectTypeString(typeOf.Elem())
    66  	case reflect.Struct:
    67  		var fields string
    68  		if numFields := typeOf.NumField(); numFields > 0 {
    69  			var sList = make([]string, numFields)
    70  			for i := range sList {
    71  				var structField reflect.StructField = typeOf.FieldByIndex([]int{i})
    72  				sList[i] = reflectTypeString(structField.Type)
    73  			}
    74  			fields = strings.Join(sList, "; ") + " "
    75  		}
    76  		return "struct{ " + fields + "}"
    77  	case reflect.Slice:
    78  		return "[]" + reflectTypeString(typeOf.Elem())
    79  	case reflect.Array:
    80  		return "[" + strconv.Itoa(typeOf.Len()) + "]" + reflectTypeString(typeOf.Elem())
    81  	case reflect.Int, reflect.Uint:
    82  		return kindOf.String() + bitSize // "int(64)"
    83  	default:
    84  		return kindOf.String()
    85  	}
    86  }