gitee.com/quant1x/gox@v1.21.2/encoding/binary/struc/field.go (about) 1 package struc 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "math" 8 "reflect" 9 ) 10 11 type Field struct { 12 Name string 13 Ptr bool 14 Index int 15 Type Type 16 defType Type 17 Array bool 18 Slice bool 19 Len int 20 Order binary.ByteOrder 21 Sizeof []int 22 Sizefrom []int 23 Fields Fields 24 kind reflect.Kind 25 } 26 27 func (f *Field) String() string { 28 var out string 29 if f.Type == Pad { 30 return fmt.Sprintf("{type: Pad, len: %d}", f.Len) 31 } else { 32 out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order) 33 } 34 if f.Sizefrom != nil { 35 out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom) 36 } else if f.Len > 0 { 37 out += fmt.Sprintf(", len: %d", f.Len) 38 } 39 if f.Sizeof != nil { 40 out += fmt.Sprintf(", sizeof: %v", f.Sizeof) 41 } 42 return "{" + out + "}" 43 } 44 45 func (f *Field) Size(val reflect.Value, options *Options) int { 46 typ := f.Type.Resolve(options) 47 size := 0 48 if typ == Struct { 49 vals := []reflect.Value{val} 50 if f.Slice { 51 vals = make([]reflect.Value, val.Len()) 52 for i := 0; i < val.Len(); i++ { 53 vals[i] = val.Index(i) 54 } 55 } 56 for _, val := range vals { 57 size += f.Fields.Sizeof(val, options) 58 } 59 } else if typ == Pad { 60 size = f.Len 61 } else if f.Slice || f.kind == reflect.String { 62 length := val.Len() 63 if f.Len > 1 { 64 length = f.Len 65 } 66 size = length * typ.Size() 67 } else if typ == CustomType { 68 return val.Addr().Interface().(Custom).Size(options) 69 } else { 70 size = typ.Size() 71 } 72 align := options.ByteAlign 73 if align > 0 && size < align { 74 size = align 75 } 76 return size 77 } 78 79 func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) { 80 order := f.Order 81 if options.Order != nil { 82 order = options.Order 83 } 84 if f.Ptr { 85 val = val.Elem() 86 } 87 typ := f.Type.Resolve(options) 88 switch typ { 89 case Struct: 90 return f.Fields.Pack(buf, val, options) 91 case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64: 92 size = typ.Size() 93 var n uint64 94 switch f.kind { 95 case reflect.Bool: 96 if val.Bool() { 97 n = 1 98 } else { 99 n = 0 100 } 101 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 102 n = uint64(val.Int()) 103 default: 104 n = val.Uint() 105 } 106 switch typ { 107 case Bool: 108 if n != 0 { 109 buf[0] = 1 110 } else { 111 buf[0] = 0 112 } 113 case Int8, Uint8: 114 buf[0] = byte(n) 115 case Int16, Uint16: 116 order.PutUint16(buf, uint16(n)) 117 case Int32, Uint32: 118 order.PutUint32(buf, uint32(n)) 119 case Int64, Uint64: 120 order.PutUint64(buf, uint64(n)) 121 } 122 case Float32, Float64: 123 size = typ.Size() 124 n := val.Float() 125 switch typ { 126 case Float32: 127 order.PutUint32(buf, math.Float32bits(float32(n))) 128 case Float64: 129 order.PutUint64(buf, math.Float64bits(n)) 130 } 131 case String: 132 switch f.kind { 133 case reflect.String: 134 size = val.Len() 135 copy(buf, []byte(val.String())) 136 default: 137 // TODO: handle kind != bytes here 138 size = val.Len() 139 copy(buf, val.Bytes()) 140 } 141 case CustomType: 142 return val.Addr().Interface().(Custom).Pack(buf, options) 143 default: 144 panic(fmt.Sprintf("no pack handler for type: %s", typ)) 145 } 146 return 147 } 148 149 func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) { 150 typ := f.Type.Resolve(options) 151 if typ == Pad { 152 for i := 0; i < length; i++ { 153 buf[i] = 0 154 } 155 return length, nil 156 } 157 if f.Slice { 158 // special case strings and byte slices for performance 159 end := val.Len() 160 if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) { 161 var tmp []byte 162 if f.kind == reflect.String { 163 tmp = []byte(val.String()) 164 } else { 165 tmp = val.Bytes() 166 } 167 copy(buf, tmp) 168 if end < length { 169 // TODO: allow configuring pad byte? 170 rep := bytes.Repeat([]byte{0}, length-end) 171 copy(buf[end:], rep) 172 return length, nil 173 } 174 return val.Len(), nil 175 } 176 pos := 0 177 var zero reflect.Value 178 if end < length { 179 zero = reflect.Zero(val.Type().Elem()) 180 } 181 for i := 0; i < length; i++ { 182 cur := zero 183 if i < end { 184 cur = val.Index(i) 185 } 186 if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil { 187 return pos, err 188 } else { 189 pos += n 190 } 191 } 192 return pos, nil 193 } else { 194 return f.packVal(buf, val, length, options) 195 } 196 } 197 198 func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error { 199 order := f.Order 200 if options.Order != nil { 201 order = options.Order 202 } 203 if f.Ptr { 204 val = val.Elem() 205 } 206 typ := f.Type.Resolve(options) 207 switch typ { 208 case Float32, Float64: 209 var n float64 210 switch typ { 211 case Float32: 212 n = float64(math.Float32frombits(order.Uint32(buf))) 213 case Float64: 214 n = math.Float64frombits(order.Uint64(buf)) 215 } 216 switch f.kind { 217 case reflect.Float32, reflect.Float64: 218 val.SetFloat(n) 219 default: 220 return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String()) 221 } 222 case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64: 223 var n uint64 224 switch typ { 225 case Int8: 226 n = uint64(int64(int8(buf[0]))) 227 case Int16: 228 n = uint64(int64(int16(order.Uint16(buf)))) 229 case Int32: 230 n = uint64(int64(int32(order.Uint32(buf)))) 231 case Int64: 232 n = uint64(int64(order.Uint64(buf))) 233 case Bool, Uint8: 234 n = uint64(buf[0]) 235 case Uint16: 236 n = uint64(order.Uint16(buf)) 237 case Uint32: 238 n = uint64(order.Uint32(buf)) 239 case Uint64: 240 n = uint64(order.Uint64(buf)) 241 } 242 switch f.kind { 243 case reflect.Bool: 244 val.SetBool(n != 0) 245 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 246 val.SetInt(int64(n)) 247 default: 248 val.SetUint(n) 249 } 250 default: 251 panic(fmt.Sprintf("no unpack handler for type: %s", typ)) 252 } 253 return nil 254 } 255 256 func (f *Field) Unpack(buf []byte, val reflect.Value, length int, options *Options) error { 257 typ := f.Type.Resolve(options) 258 if typ == Pad || f.kind == reflect.String { 259 if typ == Pad { 260 return nil 261 } else { 262 val.SetString(string(buf)) 263 return nil 264 } 265 } else if f.Slice { 266 if val.Cap() < length { 267 val.Set(reflect.MakeSlice(val.Type(), length, length)) 268 } else if val.Len() < length { 269 val.Set(val.Slice(0, length)) 270 } 271 // special case byte slices for performance 272 if !f.Array && typ == Uint8 && f.defType == Uint8 { 273 copy(val.Bytes(), buf[:length]) 274 return nil 275 } 276 pos := 0 277 size := typ.Size() 278 for i := 0; i < length; i++ { 279 if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil { 280 return err 281 } 282 pos += size 283 } 284 return nil 285 } else { 286 return f.unpackVal(buf, val, length, options) 287 } 288 }