github.com/niubaoshu/gotiny@v0.0.4-0.20211018120156-10d393f19ad0/utils.go (about) 1 package gotiny 2 3 import ( 4 "encoding" 5 "encoding/gob" 6 "reflect" 7 "strings" 8 "unsafe" 9 ) 10 11 const ( 12 ptr1Size = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const 13 ) 14 15 func float64ToUint64(v unsafe.Pointer) uint64 { 16 return reverse64Byte(*(*uint64)(v)) 17 } 18 19 func uint64ToFloat64(u uint64) float64 { 20 u = reverse64Byte(u) 21 return *((*float64)(unsafe.Pointer(&u))) 22 } 23 24 func reverse64Byte(u uint64) uint64 { 25 u = (u << 32) | (u >> 32) 26 u = ((u << 16) & 0xFFFF0000FFFF0000) | ((u >> 16) & 0xFFFF0000FFFF) 27 u = ((u << 8) & 0xFF00FF00FF00FF00) | ((u >> 8) & 0xFF00FF00FF00FF) 28 return u 29 } 30 31 func float32ToUint32(v unsafe.Pointer) uint32 { 32 return reverse32Byte(*(*uint32)(v)) 33 } 34 35 func uint32ToFloat32(u uint32) float32 { 36 u = reverse32Byte(u) 37 return *((*float32)(unsafe.Pointer(&u))) 38 } 39 40 func reverse32Byte(u uint32) uint32 { 41 u = (u << 16) | (u >> 16) 42 return ((u << 8) & 0xFF00FF00) | ((u >> 8) & 0xFF00FF) 43 } 44 45 // int -5 -4 -3 -2 -1 0 1 2 3 4 5 6 46 // uint 9 7 5 3 1 0 2 4 6 8 10 12 47 func int64ToUint64(v int64) uint64 { 48 return uint64((v << 1) ^ (v >> 63)) 49 } 50 51 // uint 9 7 5 3 1 0 2 4 6 8 10 12 52 // int -5 -4 -3 -2 -1 0 1 2 3 4 5 6 53 func uint64ToInt64(u uint64) int64 { 54 v := int64(u) 55 return (-(v & 1)) ^ (v>>1)&0x7FFFFFFFFFFFFFFF 56 } 57 58 // int -5 -4 -3 -2 -1 0 1 2 3 4 5 6 59 // uint 9 7 5 3 1 0 2 4 6 8 10 12 60 func int32ToUint32(v int32) uint32 { 61 return uint32((v << 1) ^ (v >> 31)) 62 } 63 64 // uint 9 7 5 3 1 0 2 4 6 8 10 12 65 // int -5 -4 -3 -2 -1 0 1 2 3 4 5 6 66 func uint32ToInt32(u uint32) int32 { 67 v := int32(u) 68 return (-(v & 1)) ^ (v>>1)&0x7FFFFFFF 69 } 70 71 // int -5 -4 -3 -2 -1 0 1 2 3 4 5 6 72 // uint 9 7 5 3 1 0 2 4 6 8 10 12 73 func int16ToUint16(v int16) uint16 { 74 return uint16((v << 1) ^ (v >> 15)) 75 } 76 77 // uint 9 7 5 3 1 0 2 4 6 8 10 12 78 // int -5 -4 -3 -2 -1 0 1 2 3 4 5 6 79 func uint16ToInt16(u uint16) int16 { 80 v := int16(u) 81 return (-(v & 1)) ^ (v>>1)&0x7FFF 82 } 83 84 func isNil(p unsafe.Pointer) bool { 85 return *(*unsafe.Pointer)(p) == nil 86 } 87 88 type gobInter interface { 89 gob.GobEncoder 90 gob.GobDecoder 91 } 92 93 type binInter interface { 94 encoding.BinaryMarshaler 95 encoding.BinaryUnmarshaler 96 } 97 98 // 只应该由指针来实现该接口 99 type GoTinySerializer interface { 100 // 编码方法,将对象的序列化结果append到入参数并返回,方法不应该修改入参数值原有的值 101 GotinyEncode([]byte) []byte 102 // 解码方法,将入参解码到对象里并返回使用的长度。方法从入参的第0个字节开始使用,并且不应该修改入参中的任何数据 103 GotinyDecode([]byte) int 104 } 105 106 func implementOtherSerializer(rt reflect.Type) (encEng encEng, decEng decEng) { 107 rtNil := reflect.Zero(reflect.PtrTo(rt)).Interface() 108 if _, ok := rtNil.(GoTinySerializer); ok { 109 encEng = func(e *Encoder, p unsafe.Pointer) { 110 e.buf = reflect.NewAt(rt, p).Interface().(GoTinySerializer).GotinyEncode(e.buf) 111 } 112 decEng = func(d *Decoder, p unsafe.Pointer) { 113 d.index += reflect.NewAt(rt, p).Interface().(GoTinySerializer).GotinyDecode(d.buf[d.index:]) 114 } 115 return 116 } 117 118 if _, ok := rtNil.(binInter); ok { 119 encEng = func(e *Encoder, p unsafe.Pointer) { 120 buf, err := reflect.NewAt(rt, p).Interface().(encoding.BinaryMarshaler).MarshalBinary() 121 if err != nil { 122 panic(err) 123 } 124 e.encLength(len(buf)) 125 e.buf = append(e.buf, buf...) 126 } 127 128 decEng = func(d *Decoder, p unsafe.Pointer) { 129 length := d.decLength() 130 start := d.index 131 d.index += length 132 if err := reflect.NewAt(rt, p).Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(d.buf[start:d.index]); err != nil { 133 panic(err) 134 } 135 } 136 return 137 } 138 139 if _, ok := rtNil.(gobInter); ok { 140 encEng = func(e *Encoder, p unsafe.Pointer) { 141 buf, err := reflect.NewAt(rt, p).Interface().(gob.GobEncoder).GobEncode() 142 if err != nil { 143 panic(err) 144 } 145 e.encLength(len(buf)) 146 e.buf = append(e.buf, buf...) 147 } 148 decEng = func(d *Decoder, p unsafe.Pointer) { 149 length := d.decLength() 150 start := d.index 151 d.index += length 152 if err := reflect.NewAt(rt, p).Interface().(gob.GobDecoder).GobDecode(d.buf[start:d.index]); err != nil { 153 panic(err) 154 } 155 } 156 } 157 return 158 } 159 160 // rt.kind is reflect.struct 161 func getFieldType(rt reflect.Type, baseOff uintptr) (fields []reflect.Type, offs []uintptr) { 162 for i := 0; i < rt.NumField(); i++ { 163 field := rt.Field(i) 164 if ignoreField(field) { 165 continue 166 } 167 ft := field.Type 168 if ft.Kind() == reflect.Struct { 169 if _, engine := implementOtherSerializer(ft); engine == nil { 170 fFields, fOffs := getFieldType(ft, field.Offset+baseOff) 171 fields = append(fields, fFields...) 172 offs = append(offs, fOffs...) 173 continue 174 } 175 } 176 fields = append(fields, ft) 177 offs = append(offs, field.Offset+baseOff) 178 } 179 return 180 } 181 182 func ignoreField(field reflect.StructField) bool { 183 tinyTag, ok := field.Tag.Lookup("gotiny") 184 return ok && strings.TrimSpace(tinyTag) == "-" 185 }