github.com/andeya/ameda@v1.5.3/typconv.go (about)

     1  package ameda
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  )
     7  
     8  // UnsafeBytesToString convert []byte type to string type.
     9  func UnsafeBytesToString(b []byte) string {
    10  	return *(*string)(unsafe.Pointer(&b))
    11  }
    12  
    13  // UnsafeStringToBytes convert string type to []byte type.
    14  // NOTE:
    15  //
    16  //	panic if modify the member value of the []byte.
    17  func UnsafeStringToBytes(s string) []byte {
    18  	return *(*[]byte)(unsafe.Pointer(
    19  		&struct {
    20  			string
    21  			Cap int
    22  		}{s, len(s)},
    23  	))
    24  }
    25  
    26  // IndirectValue gets the indirect value.
    27  func IndirectValue(v reflect.Value) reflect.Value {
    28  	if !v.IsValid() {
    29  		return v
    30  	}
    31  	if v.Kind() != reflect.Ptr {
    32  		// Avoid creating a reflect.Value if it's not a pointer.
    33  		return v
    34  	}
    35  	for v.Kind() == reflect.Ptr && !v.IsNil() {
    36  		v = v.Elem()
    37  	}
    38  	return v
    39  }
    40  
    41  // DereferenceType dereference, get the underlying non-pointer type.
    42  func DereferenceType(t reflect.Type) reflect.Type {
    43  	for t.Kind() == reflect.Ptr {
    44  		t = t.Elem()
    45  	}
    46  	return t
    47  }
    48  
    49  // DereferenceValue dereference and unpack interface,
    50  // get the underlying non-pointer and non-interface value.
    51  func DereferenceValue(v reflect.Value) reflect.Value {
    52  	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
    53  		v = v.Elem()
    54  	}
    55  	return v
    56  }
    57  
    58  // DereferencePtrValue returns the underlying non-pointer type value.
    59  func DereferencePtrValue(v reflect.Value) reflect.Value {
    60  	for v.Kind() == reflect.Ptr {
    61  		v = v.Elem()
    62  	}
    63  	return v
    64  }
    65  
    66  // DereferenceInterfaceValue returns the value of the underlying type that implements the interface v.
    67  func DereferenceInterfaceValue(v reflect.Value) reflect.Value {
    68  	for v.Kind() == reflect.Interface {
    69  		v = v.Elem()
    70  	}
    71  	return v
    72  }
    73  
    74  // DereferenceImplementType returns the underlying type of the value that implements the interface v.
    75  func DereferenceImplementType(v reflect.Value) reflect.Type {
    76  	return DereferenceType(DereferenceInterfaceValue(v).Type())
    77  }
    78  
    79  // DereferenceSlice convert []*T to []T.
    80  func DereferenceSlice(v reflect.Value) reflect.Value {
    81  	m := v.Len() - 1
    82  	if m < 0 {
    83  		return reflect.New(reflect.SliceOf(DereferenceType(v.Type().Elem()))).Elem()
    84  	}
    85  	s := make([]reflect.Value, m+1)
    86  	for ; m >= 0; m-- {
    87  		s[m] = DereferenceValue(v.Index(m))
    88  	}
    89  	v = reflect.New(reflect.SliceOf(s[0].Type())).Elem()
    90  	v = reflect.Append(v, s...)
    91  	return v
    92  }
    93  
    94  // ReferenceSlice convert []T to []*T, the ptrDepth is the count of '*'.
    95  func ReferenceSlice(v reflect.Value, ptrDepth int) reflect.Value {
    96  	if ptrDepth <= 0 {
    97  		return v
    98  	}
    99  	m := v.Len() - 1
   100  	if m < 0 {
   101  		return reflect.New(reflect.SliceOf(ReferenceType(v.Type().Elem(), ptrDepth))).Elem()
   102  	}
   103  	s := make([]reflect.Value, m+1)
   104  	for ; m >= 0; m-- {
   105  		s[m] = ReferenceValue(v.Index(m), ptrDepth)
   106  	}
   107  	v = reflect.New(reflect.SliceOf(s[0].Type())).Elem()
   108  	v = reflect.Append(v, s...)
   109  	return v
   110  }
   111  
   112  // ReferenceType convert T to *T, the ptrDepth is the count of '*'.
   113  func ReferenceType(t reflect.Type, ptrDepth int) reflect.Type {
   114  	switch {
   115  	case ptrDepth > 0:
   116  		for ; ptrDepth > 0; ptrDepth-- {
   117  			t = reflect.PtrTo(t)
   118  		}
   119  	case ptrDepth < 0:
   120  		for ; ptrDepth < 0 && t.Kind() == reflect.Ptr; ptrDepth++ {
   121  			t = t.Elem()
   122  		}
   123  	}
   124  	return t
   125  }
   126  
   127  // ReferenceValue convert T to *T, the ptrDepth is the count of '*'.
   128  func ReferenceValue(v reflect.Value, ptrDepth int) reflect.Value {
   129  	switch {
   130  	case ptrDepth > 0:
   131  		for ; ptrDepth > 0; ptrDepth-- {
   132  			vv := reflect.New(v.Type())
   133  			vv.Elem().Set(v)
   134  			v = vv
   135  		}
   136  	case ptrDepth < 0:
   137  		for ; ptrDepth < 0 && v.Kind() == reflect.Ptr; ptrDepth++ {
   138  			v = v.Elem()
   139  		}
   140  	}
   141  	return v
   142  }