20 Order binary.ByteOrder
27 func (f *Field) String() string {
30 return fmt.Sprintf("{type: Pad, len: %d}", f.Len)
32 out = fmt.Sprintf("type: %s, order: %v", f.Type.String(), f.Order)
34 if f.Sizefrom != nil {
35 out += fmt.Sprintf(", sizefrom: %v", f.Sizefrom)
37 out += fmt.Sprintf(", len: %d", f.Len)
40 out += fmt.Sprintf(", sizeof: %v", f.Sizeof)
42 return "{" + out + "}"
45 func (f *Field) Size(val reflect.Value, options *Options) int {
46 typ := f.Type.Resolve(options)
49 vals := []reflect.Value{val}
51 vals = make([]reflect.Value, val.Len())
52 for i := 0; i < val.Len(); i++ {
53 vals[i] = val.Index(i)
56 for _, val := range vals {
57 size += f.Fields.Sizeof(val, options)
59 } else if typ == Pad {
61 } else if f.Slice || f.kind == reflect.String {
66 size = length * typ.Size()
67 } else if typ == CustomType {
68 return val.Addr().Interface().(Custom).Size(options)
72 align := options.ByteAlign
73 if align > 0 && size < align {
79 func (f *Field) packVal(buf []byte, val reflect.Value, length int, options *Options) (size int, err error) {
81 if options.Order != nil {
87 typ := f.Type.Resolve(options)
90 return f.Fields.Pack(buf, val, options)
91 case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
101 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
102 n = uint64(val.Int())
116 order.PutUint16(buf, uint16(n))
118 order.PutUint32(buf, uint32(n))
120 order.PutUint64(buf, uint64(n))
122 case Float32, Float64:
127 order.PutUint32(buf, math.Float32bits(float32(n)))
129 order.PutUint64(buf, math.Float64bits(n))
135 copy(buf, []byte(val.String()))
137 // TODO: handle kind != bytes here
139 copy(buf, val.Bytes())
142 return val.Addr().Interface().(Custom).Pack(buf, options)
144 panic(fmt.Sprintf("no pack handler for type: %s", typ))
149 func (f *Field) Pack(buf []byte, val reflect.Value, length int, options *Options) (int, error) {
150 typ := f.Type.Resolve(options)
152 for i := 0; i < length; i++ {
158 // special case strings and byte slices for performance
160 if !f.Array && typ == Uint8 && (f.defType == Uint8 || f.kind == reflect.String) {
162 if f.kind == reflect.String {
163 tmp = []byte(val.String())
169 // TODO: allow configuring pad byte?
170 rep := bytes.Repeat([]byte{0}, length-end)
174 return val.Len(), nil
177 var zero reflect.Value
179 zero = reflect.Zero(val.Type().Elem())
181 for i := 0; i < length; i++ {
186 if n, err := f.packVal(buf[pos:], cur, 1, options); err != nil {
194 return f.packVal(buf, val, length, options)
198 func (f *Field) unpackVal(buf []byte, val reflect.Value, length int, options *Options) error {
200 if options.Order != nil {
201 order = options.Order
206 typ := f.Type.Resolve(options)
208 case Float32, Float64:
212 n = float64(math.Float32frombits(order.Uint32(buf)))
214 n = math.Float64frombits(order.Uint64(buf))
217 case reflect.Float32, reflect.Float64:
220 return fmt.Errorf("struc: refusing to unpack float into field %s of type %s", f.Name, f.kind.String())
222 case Bool, Int8, Int16, Int32, Int64, Uint8, Uint16, Uint32, Uint64:
226 n = uint64(int64(int8(buf[0])))
228 n = uint64(int64(int16(order.Uint16(buf))))
230 n = uint64(int64(int32(order.Uint32(buf))))
232 n = uint64(int64(order.Uint64(buf)))
236 n = uint64(order.Uint16(buf))
238 n = uint64(order.Uint32(buf))
240 n = uint64(order.Uint64(buf))
245 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
251 panic(fmt.Sprintf("no unpack handler for type: %s", typ))
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 {
262 val.SetString(string(buf))
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))
271 // special case byte slices for performance
272 if !f.Array && typ == Uint8 && f.defType == Uint8 {
273 copy(val.Bytes(), buf[:length])
278 for i := 0; i < length; i++ {
279 if err := f.unpackVal(buf[pos:pos+size], val.Index(i), 1, options); err != nil {
286 return f.unpackVal(buf, val, length, options)