gitee.com/quant1x/gox@v1.21.2/encoding/binary/cstruct/properties.go (about) 1 package cstruct 2 3 import ( 4 "reflect" 5 "sync" 6 ) 7 8 // StructProperties 9 10 type StructProperties struct { 11 Prop []*Properties 12 fixedSize int 13 } 14 15 var ( 16 propertiesMu sync.RWMutex 17 propertiesMap = make(map[reflect.Type]*StructProperties) 18 ) 19 20 func GetProperties(t reflect.Type) *StructProperties { 21 if t.Kind() != reflect.Struct { 22 panic("cstruct: type must have kind cstruct") 23 } 24 25 propertiesMu.RLock() 26 sprop, ok := propertiesMap[t] 27 propertiesMu.RUnlock() 28 if ok { 29 return sprop 30 } 31 32 propertiesMu.Lock() 33 defer propertiesMu.Unlock() 34 sprop = getPropertiesLocked(t) 35 return sprop 36 } 37 38 func getPropertiesLocked(t reflect.Type) *StructProperties { 39 if prop, ok := propertiesMap[t]; ok { 40 return prop 41 } 42 43 prop := new(StructProperties) 44 propertiesMap[t] = prop 45 prop.Prop = make([]*Properties, t.NumField()) 46 for i := 0; i < t.NumField(); i++ { 47 f := t.Field(i) 48 p := new(Properties) 49 name := f.Name 50 p.init(f.Type, name, "", &f, &prop.fixedSize) 51 prop.Prop[i] = p 52 } 53 54 return prop 55 } 56 57 // Properties 58 59 type encoder func(p *Buffer, prop *Properties, base structPointer) error 60 type decoder func(p *Buffer, prop *Properties, base structPointer) error 61 type sizer func(p *Buffer, prop *Properties, base structPointer) int 62 63 type Properties struct { 64 Name string 65 field field 66 enc encoder 67 dec decoder 68 siz sizer 69 t reflect.Type 70 stype reflect.Type 71 sprop *StructProperties 72 } 73 74 func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, fixedSize *int) { 75 p.Name = name 76 if f != nil { 77 p.field = toField(f) 78 } 79 p.setEncAndDec(typ, f, fixedSize) 80 } 81 82 func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, fixedSize *int) { 83 p.enc = nil 84 p.dec = nil 85 p.siz = nil 86 p.t = typ 87 88 switch typ.Kind() { 89 case reflect.Bool: // bool 90 p.enc = (*Buffer).enc_bool 91 p.dec = (*Buffer).dec_bool 92 *fixedSize += 1 93 case reflect.Int8, reflect.Uint8: // int8 uint8 94 p.enc = (*Buffer).enc_uint8 95 p.dec = (*Buffer).dec_uint8 96 *fixedSize += 1 97 case reflect.Int16, reflect.Uint16: // int16 uint16 98 p.enc = (*Buffer).enc_uint16 99 p.dec = (*Buffer).dec_uint16 100 *fixedSize += 2 101 case reflect.Int32, reflect.Uint32, reflect.Float32: // int32 uint32 float32 102 p.enc = (*Buffer).enc_uint32 103 p.dec = (*Buffer).dec_uint32 104 *fixedSize += 4 105 case reflect.Int64, reflect.Uint64, reflect.Float64: // int64 uint64 float64 106 p.enc = (*Buffer).enc_uint64 107 p.dec = (*Buffer).dec_uint64 108 *fixedSize += 8 109 case reflect.String: // string 110 p.enc = (*Buffer).enc_string 111 p.dec = (*Buffer).dec_string 112 p.siz = (*Buffer).size_string 113 *fixedSize += 2 114 case reflect.Ptr: // cstruct ptr 115 if t2 := typ.Elem(); t2.Kind() == reflect.Struct { 116 p.stype = t2 117 p.sprop = getPropertiesLocked(p.stype) 118 p.enc = (*Buffer).enc_substruct_ptr 119 p.dec = (*Buffer).dec_substruct_ptr 120 p.siz = (*Buffer).size_substruct_ptr 121 } else { 122 panic("cstruct: unknow type. field name =" + f.Name) 123 } 124 case reflect.Struct: // cstruct 125 p.stype = typ 126 p.sprop = getPropertiesLocked(p.stype) 127 p.enc = (*Buffer).enc_substruct 128 p.dec = (*Buffer).dec_substruct 129 p.siz = (*Buffer).size_substruct 130 case reflect.Slice: 131 *fixedSize += 2 132 switch t2 := typ.Elem(); t2.Kind() { 133 case reflect.Uint8, reflect.Int8: // []byte []uint8 []int8 134 p.enc = (*Buffer).enc_slice_byte 135 p.dec = (*Buffer).dec_slice_byte 136 p.siz = (*Buffer).size_slice_byte 137 case reflect.Bool: // []bool 138 p.enc = (*Buffer).enc_slice_bool 139 p.dec = (*Buffer).dec_slice_bool 140 p.siz = (*Buffer).size_slice_bool 141 case reflect.Uint16, reflect.Int16: // []uint16 []int16 142 p.enc = (*Buffer).enc_slice_uint16 143 p.dec = (*Buffer).dec_slice_uint16 144 p.siz = (*Buffer).size_slice_uint16 145 case reflect.Uint32, reflect.Int32, reflect.Float32: // []uint32 []int32 []float32 146 p.enc = (*Buffer).enc_slice_uint32 147 p.dec = (*Buffer).dec_slice_uint32 148 p.siz = (*Buffer).size_slice_uint32 149 case reflect.Uint64, reflect.Int64, reflect.Float64: // []uint64 []int64 []float64 150 p.enc = (*Buffer).enc_slice_uint64 151 p.dec = (*Buffer).dec_slice_uint64 152 p.siz = (*Buffer).size_slice_uint64 153 case reflect.String: // []string 154 p.enc = (*Buffer).enc_slice_string 155 p.dec = (*Buffer).dec_slice_string 156 p.siz = (*Buffer).size_slice_string 157 case reflect.Struct: // [] cstruct 158 p.stype = t2 159 p.sprop = getPropertiesLocked(p.stype) 160 p.enc = (*Buffer).enc_slice_substruct 161 p.dec = (*Buffer).dec_slice_substruct 162 p.siz = (*Buffer).size_slice_substruct 163 case reflect.Ptr: // []*cstruct 164 switch t3 := t2.Elem(); t3.Kind() { 165 case reflect.Struct: 166 p.stype = t3 167 p.sprop = getPropertiesLocked(p.stype) 168 if OptionSliceIgnoreNil == false { 169 p.enc = (*Buffer).enc_slice_substruct_ptr 170 p.dec = (*Buffer).dec_slice_substruct_ptr 171 p.siz = (*Buffer).size_slice_substruct_ptr 172 } else { 173 p.enc = (*Buffer).enc_slice_substruct_ptr_ignore_nil 174 p.dec = (*Buffer).dec_slice_substruct_ptr_ignore_nil 175 p.siz = (*Buffer).size_slice_substruct_ptr_ignore_nil 176 } 177 default: 178 panic("cstruct: unknow type. field name = " + f.Name) 179 } 180 case reflect.Slice: 181 switch t2.Elem().Kind() { 182 case reflect.Uint8: 183 p.enc = (*Buffer).enc_slice_slice_byte 184 p.dec = (*Buffer).dec_slice_slice_byte 185 p.siz = (*Buffer).size_slice_slice_byte 186 default: 187 panic("cstruct: unknow type. field name = " + f.Name) 188 } 189 default: 190 panic("cstruct: unknow type. field name = " + f.Name) 191 } 192 case reflect.Array: 193 switch t2 := typ.Elem(); t2.Kind() { 194 case reflect.Uint8, reflect.Int8, reflect.Bool: // [n]byte [n]uint8 [n]int8 [n]bool 195 p.enc = (*Buffer).enc_array_byte 196 p.dec = (*Buffer).dec_array_byte 197 p.siz = (*Buffer).size_array_byte 198 case reflect.Uint16, reflect.Int16: // [n]uint16 [n]int16 199 p.enc = (*Buffer).enc_array_uint16 200 p.dec = (*Buffer).dec_array_uint16 201 p.siz = (*Buffer).size_array_uint16 202 case reflect.Uint32, reflect.Int32, reflect.Float32: // [n]uint32 [n]int32 [n]float32 203 p.enc = (*Buffer).enc_array_uint32 204 p.dec = (*Buffer).dec_array_uint32 205 p.siz = (*Buffer).size_array_uint32 206 case reflect.Uint64, reflect.Int64, reflect.Float64: // [n]uint64 [n]int64 [n]float64 207 p.enc = (*Buffer).enc_array_uint64 208 p.dec = (*Buffer).dec_array_uint64 209 p.siz = (*Buffer).size_array_uint64 210 case reflect.Struct: // [n]cstruct 211 p.stype = t2 212 p.sprop = getPropertiesLocked(p.stype) 213 p.enc = (*Buffer).enc_array_substruct 214 p.dec = (*Buffer).dec_array_substruct 215 p.siz = (*Buffer).size_array_substruct 216 default: 217 panic("cstruct: unknow type. field name = " + f.Name) 218 } 219 default: 220 panic("cstruct: unknow type. field name = " + f.Name) 221 } 222 }