...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package apk
18
19 import (
20 "encoding/binary"
21 "fmt"
22 "io"
23 "reflect"
24
25 "github.com/pkg/errors"
26 )
27
28
29
30
31 var errTrailingData = errors.New("trailing data after structure")
32
33 type apkRaw []byte
34
35
36 func (r apkRaw) Bytes() []byte {
37 return []byte(r[4:])
38 }
39
40 var (
41 bytesType = reflect.TypeOf([]byte(nil))
42 rawType = reflect.TypeOf(apkRaw(nil))
43 uint32Type = reflect.TypeOf(uint32(0))
44 )
45
46 func unmarshal(blob []byte, dest interface{}) error {
47 v := reflect.ValueOf(dest)
48 if v.Kind() != reflect.Ptr || v.IsNil() {
49 return errors.New("target of unmarshal must be a non-nil pointer")
50 }
51 v = v.Elem()
52 blob, err := unmarshalR(blob, v)
53 if err != nil {
54 return err
55 } else if len(blob) != 0 {
56 return errTrailingData
57 }
58 return nil
59 }
60
61 func unmarshalR(blob []byte, v reflect.Value ) ([]byte, error) {
62
63 switch {
64 case v.Type() == uint32Type:
65 if len(blob) < 4 {
66 return nil, io.ErrUnexpectedEOF
67 }
68 i := binary.LittleEndian.Uint32(blob)
69
70 v.SetUint(uint64(i))
71 return blob[4:], nil
72 }
73
74 if len(blob) < 4 {
75 return nil, io.ErrUnexpectedEOF
76 }
77 size := int(binary.LittleEndian.Uint32(blob))
78 if 4+len(blob) < size {
79 return nil, io.ErrUnexpectedEOF
80 }
81 remainder := blob[4+size:]
82 raw := blob[:4+size]
83 blob = raw[4:]
84 switch {
85 case v.Type() == bytesType:
86
87
88 v.SetBytes(blob)
89 case v.Type() == rawType:
90
91
92 v.SetBytes(raw)
93
94 case v.Kind() == reflect.Slice:
95
96 itemType := v.Type().Elem()
97
98 v.SetLen(0)
99 for len(blob) > 0 {
100 var err error
101
102 n := v.Len()
103 v.Set(reflect.Append(v, reflect.Zero(itemType)))
104 blob, err = unmarshalR(blob, v.Index(n))
105 if err != nil {
106 return nil, err
107 }
108 }
109 case v.Kind() == reflect.Struct:
110
111
112 for i := 0; i < v.NumField(); i++ {
113 var err error
114 blob, err = unmarshalR(blob, v.Field(i))
115 if err != nil {
116 return nil, err
117 }
118 }
119 if len(blob) > 0 {
120 return nil, errTrailingData
121 }
122 default:
123 panic("can't unmarshal type " + v.Type().String())
124 }
125 return remainder, nil
126 }
127
128 func marshal(src interface{}) (apkRaw, error) {
129 v := reflect.ValueOf(src)
130 m := new(marshaller)
131 if err := m.marshal(v); err != nil {
132 return nil, err
133 }
134 return apkRaw(m.buf), nil
135 }
136
137 type marshaller struct {
138 buf []byte
139 pos int
140 }
141
142 func (m *marshaller) grow(n int) []byte {
143 if cap(m.buf)-m.pos < n {
144 buf := make([]byte, 2*cap(m.buf)+n)
145 copy(buf, m.buf)
146 m.buf = buf
147 }
148 m.buf = m.buf[:m.pos+n]
149 ret := m.buf[m.pos : m.pos+n]
150 m.pos += n
151 return ret
152 }
153
154 func (m *marshaller) write(d []byte) {
155 copy(m.grow(len(d)), d)
156 }
157
158 func (m *marshaller) marshal(v reflect.Value) error {
159 if v.Type() == rawType {
160
161 m.write(v.Bytes())
162 return nil
163 }
164
165 switch {
166 case v.Type() == uint32Type:
167 binary.LittleEndian.PutUint32(m.grow(4), uint32(v.Uint()))
168 return nil
169 }
170
171 start := m.pos
172 m.grow(4)
173 switch {
174 case v.Type() == bytesType:
175
176 m.write(v.Bytes())
177 case v.Kind() == reflect.Slice:
178
179 for i := 0; i < v.Len(); i++ {
180 if err := m.marshal(v.Index(i)); err != nil {
181 return err
182 }
183 }
184 case v.Kind() == reflect.Struct:
185
186 for i := 0; i < v.NumField(); i++ {
187 if err := m.marshal(v.Field(i)); err != nil {
188 return err
189 }
190 }
191 default:
192 return fmt.Errorf("can't marshal type %s", v.Type())
193 }
194
195 end := m.pos
196 binary.LittleEndian.PutUint32(m.buf[start:], uint32(end-start-4))
197 return nil
198 }
199
View as plain text