13 func (f Fields) SetByteOrder(order binary.ByteOrder) {
14 for _, field := range f {
21 func (f Fields) String() string {
22 fields := make([]string, len(f))
23 for i, field := range f {
25 fields[i] = field.String()
28 return "{" + strings.Join(fields, ", ") + "}"
31 func (f Fields) Sizeof(val reflect.Value, options *Options) int {
32 for val.Kind() == reflect.Ptr {
36 for i, field := range f {
38 size += field.Size(val.Field(i), options)
44 func (f Fields) sizefrom(val reflect.Value, index []int) int {
45 field := val.FieldByIndex(index)
47 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
48 return int(field.Int())
49 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
50 n := int(field.Uint())
51 // all the builtin array length types are native int
52 // so this guards against weird truncation
58 name := val.Type().FieldByIndex(index).Name
59 panic(fmt.Sprintf("sizeof field %T.%s not an integer type", val.Interface(), name))
63 func (f Fields) Pack(buf []byte, val reflect.Value, options *Options) (int, error) {
64 for val.Kind() == reflect.Ptr {
68 for i, field := range f {
74 if field.Sizefrom != nil {
75 length = f.sizefrom(val, field.Sizefrom)
77 if length <= 0 && field.Slice {
80 if field.Sizeof != nil {
81 length := val.FieldByIndex(field.Sizeof).Len()
83 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
84 // allocating a new int here has fewer side effects (doesn't update the original struct)
85 // but it's a wasteful allocation
86 // the old method might work if we just cast the temporary int/uint to the target type
87 v = reflect.New(v.Type()).Elem()
88 v.SetInt(int64(length))
89 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
90 v = reflect.New(v.Type()).Elem()
91 v.SetUint(uint64(length))
93 panic(fmt.Sprintf("sizeof field is not int or uint type: %s, %s", field.Name, v.Type()))
96 if n, err := field.Pack(buf[pos:], v, length, options); err != nil {
105 func (f Fields) Unpack(r io.Reader, val reflect.Value, options *Options) error {
106 for val.Kind() == reflect.Ptr {
111 for i, field := range f {
117 if field.Sizefrom != nil {
118 length = f.sizefrom(val, field.Sizefrom)
120 if v.Kind() == reflect.Ptr && !v.Elem().IsValid() {
121 v.Set(reflect.New(v.Type().Elem()))
123 if field.Type == Struct {
125 vals := reflect.MakeSlice(v.Type(), length, length)
126 for i := 0; i < length; i++ {
128 fields, err := parseFields(v)
132 if err := fields.Unpack(r, v, options); err != nil {
138 // TODO: DRY (we repeat the inner loop above)
139 fields, err := parseFields(v)
143 if err := fields.Unpack(r, v, options); err != nil {
149 typ := field.Type.Resolve(options)
150 if typ == CustomType {
151 if err := v.Addr().Interface().(Custom).Unpack(r, length, options); err != nil {
155 size := length * field.Type.Resolve(options).Size()
159 buf = make([]byte, size)
161 if _, err := io.ReadFull(r, buf); err != nil {
164 err := field.Unpack(buf[:size], v, length, options)