github.com/niubaoshu/gotiny@v0.0.4-0.20211018120156-10d393f19ad0/encEngine.go (about) 1 package gotiny 2 3 import ( 4 "reflect" 5 "sync" 6 "time" 7 "unsafe" 8 ) 9 10 type encEng func(*Encoder, unsafe.Pointer) //编码器 11 12 var ( 13 rt2encEng = map[reflect.Type]encEng{ 14 reflect.TypeOf((*bool)(nil)).Elem(): encBool, 15 reflect.TypeOf((*int)(nil)).Elem(): encInt, 16 reflect.TypeOf((*int8)(nil)).Elem(): encInt8, 17 reflect.TypeOf((*int16)(nil)).Elem(): encInt16, 18 reflect.TypeOf((*int32)(nil)).Elem(): encInt32, 19 reflect.TypeOf((*int64)(nil)).Elem(): encInt64, 20 reflect.TypeOf((*uint)(nil)).Elem(): encUint, 21 reflect.TypeOf((*uint8)(nil)).Elem(): encUint8, 22 reflect.TypeOf((*uint16)(nil)).Elem(): encUint16, 23 reflect.TypeOf((*uint32)(nil)).Elem(): encUint32, 24 reflect.TypeOf((*uint64)(nil)).Elem(): encUint64, 25 reflect.TypeOf((*uintptr)(nil)).Elem(): encUintptr, 26 reflect.TypeOf((*unsafe.Pointer)(nil)).Elem(): encPointer, 27 reflect.TypeOf((*float32)(nil)).Elem(): encFloat32, 28 reflect.TypeOf((*float64)(nil)).Elem(): encFloat64, 29 reflect.TypeOf((*complex64)(nil)).Elem(): encComplex64, 30 reflect.TypeOf((*complex128)(nil)).Elem(): encComplex128, 31 reflect.TypeOf((*[]byte)(nil)).Elem(): encBytes, 32 reflect.TypeOf((*string)(nil)).Elem(): encString, 33 reflect.TypeOf((*time.Time)(nil)).Elem(): encTime, 34 reflect.TypeOf((*struct{})(nil)).Elem(): encIgnore, 35 reflect.TypeOf(nil): encIgnore, 36 } 37 38 encEngines = [...]encEng{ 39 reflect.Invalid: encIgnore, 40 reflect.Bool: encBool, 41 reflect.Int: encInt, 42 reflect.Int8: encInt8, 43 reflect.Int16: encInt16, 44 reflect.Int32: encInt32, 45 reflect.Int64: encInt64, 46 reflect.Uint: encUint, 47 reflect.Uint8: encUint8, 48 reflect.Uint16: encUint16, 49 reflect.Uint32: encUint32, 50 reflect.Uint64: encUint64, 51 reflect.Uintptr: encUintptr, 52 reflect.UnsafePointer: encPointer, 53 reflect.Float32: encFloat32, 54 reflect.Float64: encFloat64, 55 reflect.Complex64: encComplex64, 56 reflect.Complex128: encComplex128, 57 reflect.String: encString, 58 } 59 60 encLock sync.RWMutex 61 ) 62 63 func UnusedUnixNanoEncodeTimeType() { 64 delete(rt2encEng, reflect.TypeOf((*time.Time)(nil)).Elem()) 65 delete(rt2decEng, reflect.TypeOf((*time.Time)(nil)).Elem()) 66 } 67 68 func getEncEngine(rt reflect.Type) encEng { 69 encLock.RLock() 70 engine := rt2encEng[rt] 71 encLock.RUnlock() 72 if engine != nil { 73 return engine 74 } 75 encLock.Lock() 76 buildEncEngine(rt, &engine) 77 encLock.Unlock() 78 return engine 79 } 80 81 func buildEncEngine(rt reflect.Type, engPtr *encEng) { 82 engine := rt2encEng[rt] 83 if engine != nil { 84 *engPtr = engine 85 return 86 } 87 88 if engine, _ = implementOtherSerializer(rt); engine != nil { 89 rt2encEng[rt] = engine 90 *engPtr = engine 91 return 92 } 93 94 kind := rt.Kind() 95 var eEng encEng 96 switch kind { 97 case reflect.Ptr: 98 defer buildEncEngine(rt.Elem(), &eEng) 99 engine = func(e *Encoder, p unsafe.Pointer) { 100 isNotNil := !isNil(p) 101 e.encIsNotNil(isNotNil) 102 if isNotNil { 103 eEng(e, *(*unsafe.Pointer)(p)) 104 } 105 } 106 case reflect.Array: 107 et, l := rt.Elem(), rt.Len() 108 defer buildEncEngine(et, &eEng) 109 size := et.Size() 110 engine = func(e *Encoder, p unsafe.Pointer) { 111 for i := 0; i < l; i++ { 112 eEng(e, unsafe.Pointer(uintptr(p)+uintptr(i)*size)) 113 } 114 } 115 case reflect.Slice: 116 et := rt.Elem() 117 size := et.Size() 118 defer buildEncEngine(et, &eEng) 119 engine = func(e *Encoder, p unsafe.Pointer) { 120 isNotNil := !isNil(p) 121 e.encIsNotNil(isNotNil) 122 if isNotNil { 123 header := (*reflect.SliceHeader)(p) 124 l := header.Len 125 e.encLength(l) 126 for i := 0; i < l; i++ { 127 eEng(e, unsafe.Pointer(header.Data+uintptr(i)*size)) 128 } 129 } 130 } 131 case reflect.Map: 132 var kEng encEng 133 defer buildEncEngine(rt.Key(), &kEng) 134 defer buildEncEngine(rt.Elem(), &eEng) 135 engine = func(e *Encoder, p unsafe.Pointer) { 136 isNotNil := !isNil(p) 137 e.encIsNotNil(isNotNil) 138 if isNotNil { 139 v := reflect.NewAt(rt, p).Elem() 140 e.encLength(v.Len()) 141 keys := v.MapKeys() 142 for i := 0; i < len(keys); i++ { 143 val := v.MapIndex(keys[i]) 144 kEng(e, getUnsafePointer(&keys[i])) 145 eEng(e, getUnsafePointer(&val)) 146 } 147 } 148 } 149 case reflect.Struct: 150 fields, offs := getFieldType(rt, 0) 151 nf := len(fields) 152 fEngines := make([]encEng, nf) 153 defer func() { 154 for i := 0; i < nf; i++ { 155 buildEncEngine(fields[i], &fEngines[i]) 156 } 157 }() 158 engine = func(e *Encoder, p unsafe.Pointer) { 159 for i := 0; i < len(fEngines) && i < len(offs); i++ { 160 fEngines[i](e, unsafe.Pointer(uintptr(p)+offs[i])) 161 } 162 } 163 case reflect.Interface: 164 if rt.NumMethod() > 0 { 165 engine = func(e *Encoder, p unsafe.Pointer) { 166 isNotNil := !isNil(p) 167 e.encIsNotNil(isNotNil) 168 if isNotNil { 169 v := reflect.ValueOf(*(*interface { 170 M() 171 })(p)) 172 et := v.Type() 173 e.encString(getNameOfType(et)) 174 getEncEngine(et)(e, getUnsafePointer(&v)) 175 } 176 } 177 } else { 178 engine = func(e *Encoder, p unsafe.Pointer) { 179 isNotNil := !isNil(p) 180 e.encIsNotNil(isNotNil) 181 if isNotNil { 182 v := reflect.ValueOf(*(*interface{})(p)) 183 et := v.Type() 184 e.encString(getNameOfType(et)) 185 getEncEngine(et)(e, getUnsafePointer(&v)) 186 } 187 } 188 } 189 case reflect.Chan, reflect.Func: 190 panic("not support " + rt.String() + " type") 191 default: 192 engine = encEngines[kind] 193 } 194 rt2encEng[rt] = engine 195 *engPtr = engine 196 }