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 }