github.com/wI2L/jettison@v0.7.5-0.20230106001914-c70014c6417a/types.go (about)

     1  package jettison
     2  
     3  import (
     4  	"encoding"
     5  	"encoding/json"
     6  	"reflect"
     7  	"sync"
     8  	"time"
     9  	"unsafe"
    10  )
    11  
    12  var (
    13  	timeTimeType           = reflect.TypeOf(time.Time{})
    14  	timeDurationType       = reflect.TypeOf(time.Duration(0))
    15  	syncMapType            = reflect.TypeOf((*sync.Map)(nil)).Elem()
    16  	jsonNumberType         = reflect.TypeOf(json.Number(""))
    17  	jsonRawMessageType     = reflect.TypeOf(json.RawMessage(nil))
    18  	jsonMarshalerType      = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
    19  	textMarshalerType      = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
    20  	appendMarshalerType    = reflect.TypeOf((*AppendMarshaler)(nil)).Elem()
    21  	appendMarshalerCtxType = reflect.TypeOf((*AppendMarshalerCtx)(nil)).Elem()
    22  )
    23  
    24  var emptyFnCache sync.Map // map[reflect.Type]emptyFunc
    25  
    26  // emptyFunc is a function that returns whether a
    27  // value pointed by an unsafe.Pointer represents the
    28  // zero value of its type.
    29  type emptyFunc func(unsafe.Pointer) bool
    30  
    31  // marshalerEncodeFunc is a function that appends
    32  // the result of a marshaler method call to dst.
    33  type marshalerEncodeFunc func(interface{}, []byte, encOpts, reflect.Type) ([]byte, error)
    34  
    35  func isBasicType(t reflect.Type) bool {
    36  	return isBoolean(t) || isString(t) || isFloatingPoint(t) || isInteger(t)
    37  }
    38  
    39  func isBoolean(t reflect.Type) bool { return t.Kind() == reflect.Bool }
    40  func isString(t reflect.Type) bool  { return t.Kind() == reflect.String }
    41  
    42  func isFloatingPoint(t reflect.Type) bool {
    43  	kind := t.Kind()
    44  	if kind == reflect.Float32 || kind == reflect.Float64 {
    45  		return true
    46  	}
    47  	return false
    48  }
    49  
    50  func isInteger(t reflect.Type) bool {
    51  	switch t.Kind() {
    52  	case reflect.Int,
    53  		reflect.Int8,
    54  		reflect.Int16,
    55  		reflect.Int32,
    56  		reflect.Int64,
    57  		reflect.Uint,
    58  		reflect.Uint8,
    59  		reflect.Uint16,
    60  		reflect.Uint32,
    61  		reflect.Uint64,
    62  		reflect.Uintptr:
    63  		return true
    64  	default:
    65  		return false
    66  	}
    67  }
    68  
    69  func isInlined(t reflect.Type) bool {
    70  	switch t.Kind() {
    71  	case reflect.Ptr, reflect.Map:
    72  		return true
    73  	case reflect.Struct:
    74  		return t.NumField() == 1 && isInlined(t.Field(0).Type)
    75  	default:
    76  		return false
    77  	}
    78  }
    79  
    80  func isNilable(t reflect.Type) bool {
    81  	switch t.Kind() {
    82  	case reflect.Ptr, reflect.Interface, reflect.Slice, reflect.Map:
    83  		return true
    84  	}
    85  	return false
    86  }
    87  
    88  // cachedEmptyFuncOf is similar to emptyFuncOf, but
    89  // returns a cached function, to avoid duplicates.
    90  func cachedEmptyFuncOf(t reflect.Type) emptyFunc {
    91  	if fn, ok := emptyFnCache.Load(t); ok {
    92  		return fn.(emptyFunc)
    93  	}
    94  	fn, _ := emptyFnCache.LoadOrStore(t, emptyFuncOf(t))
    95  	return fn.(emptyFunc)
    96  }
    97  
    98  // emptyFuncOf returns a function that can be used to
    99  // determine if a value pointed by an unsafe,Pointer
   100  // represents the zero-value of type t.
   101  func emptyFuncOf(t reflect.Type) emptyFunc {
   102  	switch t.Kind() {
   103  	case reflect.Bool:
   104  		return func(p unsafe.Pointer) bool {
   105  			return !*(*bool)(p)
   106  		}
   107  	case reflect.String:
   108  		return func(p unsafe.Pointer) bool {
   109  			return (*stringHeader)(p).Len == 0
   110  		}
   111  	case reflect.Int:
   112  		return func(p unsafe.Pointer) bool {
   113  			return *(*int)(p) == 0
   114  		}
   115  	case reflect.Int8:
   116  		return func(p unsafe.Pointer) bool {
   117  			return *(*int8)(p) == 0
   118  		}
   119  	case reflect.Int16:
   120  		return func(p unsafe.Pointer) bool {
   121  			return *(*int16)(p) == 0
   122  		}
   123  	case reflect.Int32:
   124  		return func(p unsafe.Pointer) bool {
   125  			return *(*int32)(p) == 0
   126  		}
   127  	case reflect.Int64:
   128  		return func(p unsafe.Pointer) bool {
   129  			return *(*int64)(p) == 0
   130  		}
   131  	case reflect.Uint:
   132  		return func(p unsafe.Pointer) bool {
   133  			return *(*uint)(p) == 0
   134  		}
   135  	case reflect.Uint8:
   136  		return func(p unsafe.Pointer) bool {
   137  			return *(*uint8)(p) == 0
   138  		}
   139  	case reflect.Uint16:
   140  		return func(p unsafe.Pointer) bool {
   141  			return *(*uint16)(p) == 0
   142  		}
   143  	case reflect.Uint32:
   144  		return func(p unsafe.Pointer) bool {
   145  			return *(*uint32)(p) == 0
   146  		}
   147  	case reflect.Uint64:
   148  		return func(p unsafe.Pointer) bool {
   149  			return *(*uint64)(p) == 0
   150  		}
   151  	case reflect.Uintptr:
   152  		return func(p unsafe.Pointer) bool {
   153  			return *(*uintptr)(p) == 0
   154  		}
   155  	case reflect.Float32:
   156  		return func(p unsafe.Pointer) bool {
   157  			return *(*float32)(p) == 0
   158  		}
   159  	case reflect.Float64:
   160  		return func(p unsafe.Pointer) bool {
   161  			return *(*float64)(p) == 0
   162  		}
   163  	case reflect.Map:
   164  		return func(p unsafe.Pointer) bool {
   165  			return maplen(*(*unsafe.Pointer)(p)) == 0
   166  		}
   167  	case reflect.Ptr:
   168  		return func(p unsafe.Pointer) bool {
   169  			return *(*unsafe.Pointer)(p) == nil
   170  		}
   171  	case reflect.Interface:
   172  		return func(p unsafe.Pointer) bool {
   173  			return *(*unsafe.Pointer)(p) == nil
   174  		}
   175  	case reflect.Slice:
   176  		return func(p unsafe.Pointer) bool {
   177  			return (*sliceHeader)(p).Len == 0
   178  		}
   179  	case reflect.Array:
   180  		if t.Len() == 0 {
   181  			return func(unsafe.Pointer) bool { return true }
   182  		}
   183  	}
   184  	return func(unsafe.Pointer) bool { return false }
   185  }