Blame


1 4b33cdd0 2015-11-30 stephen.d package p9p
2 4b33cdd0 2015-11-30 stephen.d
3 4b33cdd0 2015-11-30 stephen.d import (
4 4b33cdd0 2015-11-30 stephen.d "bytes"
5 4b33cdd0 2015-11-30 stephen.d "encoding/binary"
6 4b33cdd0 2015-11-30 stephen.d "fmt"
7 4b33cdd0 2015-11-30 stephen.d "io"
8 4b33cdd0 2015-11-30 stephen.d "log"
9 4b33cdd0 2015-11-30 stephen.d "reflect"
10 4b33cdd0 2015-11-30 stephen.d "strings"
11 4b33cdd0 2015-11-30 stephen.d "time"
12 4b33cdd0 2015-11-30 stephen.d )
13 4b33cdd0 2015-11-30 stephen.d
14 4b33cdd0 2015-11-30 stephen.d // Codec defines the interface for encoding and decoding of 9p types.
15 4b33cdd0 2015-11-30 stephen.d // Unsupported types will throw an error.
16 4b33cdd0 2015-11-30 stephen.d type Codec interface {
17 4b33cdd0 2015-11-30 stephen.d // Unmarshal from data into the value pointed to by v.
18 4b33cdd0 2015-11-30 stephen.d Unmarshal(data []byte, v interface{}) error
19 4b33cdd0 2015-11-30 stephen.d
20 4b33cdd0 2015-11-30 stephen.d // Marshal the value v into a byte slice.
21 4b33cdd0 2015-11-30 stephen.d Marshal(v interface{}) ([]byte, error)
22 4b33cdd0 2015-11-30 stephen.d
23 4b33cdd0 2015-11-30 stephen.d // Size returns the encoded size for the target of v.
24 4b33cdd0 2015-11-30 stephen.d Size(v interface{}) int
25 4b33cdd0 2015-11-30 stephen.d }
26 4b33cdd0 2015-11-30 stephen.d
27 a0568195 2016-05-23 stevvooe // NewCodec returns a new, standard 9P2000 codec, ready for use.
28 4b33cdd0 2015-11-30 stephen.d func NewCodec() Codec {
29 4b33cdd0 2015-11-30 stephen.d return codec9p{}
30 4b33cdd0 2015-11-30 stephen.d }
31 4b33cdd0 2015-11-30 stephen.d
32 4b33cdd0 2015-11-30 stephen.d type codec9p struct{}
33 4b33cdd0 2015-11-30 stephen.d
34 4b33cdd0 2015-11-30 stephen.d func (c codec9p) Unmarshal(data []byte, v interface{}) error {
35 4b33cdd0 2015-11-30 stephen.d dec := &decoder{bytes.NewReader(data)}
36 4b33cdd0 2015-11-30 stephen.d return dec.decode(v)
37 4b33cdd0 2015-11-30 stephen.d }
38 4b33cdd0 2015-11-30 stephen.d
39 4b33cdd0 2015-11-30 stephen.d func (c codec9p) Marshal(v interface{}) ([]byte, error) {
40 4b33cdd0 2015-11-30 stephen.d var b bytes.Buffer
41 4b33cdd0 2015-11-30 stephen.d enc := &encoder{&b}
42 4b33cdd0 2015-11-30 stephen.d
43 4b33cdd0 2015-11-30 stephen.d if err := enc.encode(v); err != nil {
44 4b33cdd0 2015-11-30 stephen.d return nil, err
45 4b33cdd0 2015-11-30 stephen.d }
46 4b33cdd0 2015-11-30 stephen.d
47 4b33cdd0 2015-11-30 stephen.d return b.Bytes(), nil
48 4b33cdd0 2015-11-30 stephen.d }
49 4b33cdd0 2015-11-30 stephen.d
50 4b33cdd0 2015-11-30 stephen.d func (c codec9p) Size(v interface{}) int {
51 4b33cdd0 2015-11-30 stephen.d return int(size9p(v))
52 4b33cdd0 2015-11-30 stephen.d }
53 4b33cdd0 2015-11-30 stephen.d
54 4b33cdd0 2015-11-30 stephen.d // DecodeDir decodes a directory entry from rd using the provided codec.
55 4b33cdd0 2015-11-30 stephen.d func DecodeDir(codec Codec, rd io.Reader, d *Dir) error {
56 4b33cdd0 2015-11-30 stephen.d var ll uint16
57 4b33cdd0 2015-11-30 stephen.d
58 4b33cdd0 2015-11-30 stephen.d // pull the size off the wire
59 4b33cdd0 2015-11-30 stephen.d if err := binary.Read(rd, binary.LittleEndian, &ll); err != nil {
60 4b33cdd0 2015-11-30 stephen.d return err
61 4b33cdd0 2015-11-30 stephen.d }
62 4b33cdd0 2015-11-30 stephen.d
63 4b33cdd0 2015-11-30 stephen.d p := make([]byte, ll+2)
64 4b33cdd0 2015-11-30 stephen.d binary.LittleEndian.PutUint16(p, ll) // must have size at start
65 4b33cdd0 2015-11-30 stephen.d
66 4b33cdd0 2015-11-30 stephen.d // read out the rest of the record
67 4b33cdd0 2015-11-30 stephen.d if _, err := io.ReadFull(rd, p[2:]); err != nil {
68 4b33cdd0 2015-11-30 stephen.d return err
69 4b33cdd0 2015-11-30 stephen.d }
70 4b33cdd0 2015-11-30 stephen.d
71 4b33cdd0 2015-11-30 stephen.d return codec.Unmarshal(p, d)
72 4b33cdd0 2015-11-30 stephen.d }
73 4b33cdd0 2015-11-30 stephen.d
74 4b33cdd0 2015-11-30 stephen.d // EncodeDir writes the directory to wr.
75 4b33cdd0 2015-11-30 stephen.d func EncodeDir(codec Codec, wr io.Writer, d *Dir) error {
76 4b33cdd0 2015-11-30 stephen.d p, err := codec.Marshal(d)
77 4b33cdd0 2015-11-30 stephen.d if err != nil {
78 4b33cdd0 2015-11-30 stephen.d return err
79 4b33cdd0 2015-11-30 stephen.d }
80 4b33cdd0 2015-11-30 stephen.d
81 4b33cdd0 2015-11-30 stephen.d _, err = wr.Write(p)
82 4b33cdd0 2015-11-30 stephen.d return err
83 4b33cdd0 2015-11-30 stephen.d }
84 4b33cdd0 2015-11-30 stephen.d
85 4b33cdd0 2015-11-30 stephen.d type encoder struct {
86 4b33cdd0 2015-11-30 stephen.d wr io.Writer
87 4b33cdd0 2015-11-30 stephen.d }
88 4b33cdd0 2015-11-30 stephen.d
89 4b33cdd0 2015-11-30 stephen.d func (e *encoder) encode(vs ...interface{}) error {
90 4b33cdd0 2015-11-30 stephen.d for _, v := range vs {
91 4b33cdd0 2015-11-30 stephen.d switch v := v.(type) {
92 4b33cdd0 2015-11-30 stephen.d case uint8, uint16, uint32, uint64, FcallType, Tag, QType, Fid, Flag,
93 4b33cdd0 2015-11-30 stephen.d *uint8, *uint16, *uint32, *uint64, *FcallType, *Tag, *QType, *Fid, *Flag:
94 4b33cdd0 2015-11-30 stephen.d if err := binary.Write(e.wr, binary.LittleEndian, v); err != nil {
95 4b33cdd0 2015-11-30 stephen.d return err
96 4b33cdd0 2015-11-30 stephen.d }
97 4b33cdd0 2015-11-30 stephen.d case []byte:
98 4b33cdd0 2015-11-30 stephen.d if err := e.encode(uint32(len(v))); err != nil {
99 4b33cdd0 2015-11-30 stephen.d return err
100 4b33cdd0 2015-11-30 stephen.d }
101 4b33cdd0 2015-11-30 stephen.d
102 4b33cdd0 2015-11-30 stephen.d if err := binary.Write(e.wr, binary.LittleEndian, v); err != nil {
103 4b33cdd0 2015-11-30 stephen.d return err
104 4b33cdd0 2015-11-30 stephen.d }
105 4b33cdd0 2015-11-30 stephen.d
106 4b33cdd0 2015-11-30 stephen.d case *[]byte:
107 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
108 4b33cdd0 2015-11-30 stephen.d return err
109 4b33cdd0 2015-11-30 stephen.d }
110 4b33cdd0 2015-11-30 stephen.d case string:
111 4b33cdd0 2015-11-30 stephen.d if err := binary.Write(e.wr, binary.LittleEndian, uint16(len(v))); err != nil {
112 4b33cdd0 2015-11-30 stephen.d return err
113 4b33cdd0 2015-11-30 stephen.d }
114 4b33cdd0 2015-11-30 stephen.d
115 4b33cdd0 2015-11-30 stephen.d _, err := io.WriteString(e.wr, v)
116 4b33cdd0 2015-11-30 stephen.d if err != nil {
117 4b33cdd0 2015-11-30 stephen.d return err
118 4b33cdd0 2015-11-30 stephen.d }
119 4b33cdd0 2015-11-30 stephen.d case *string:
120 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
121 4b33cdd0 2015-11-30 stephen.d return err
122 4b33cdd0 2015-11-30 stephen.d }
123 4b33cdd0 2015-11-30 stephen.d
124 4b33cdd0 2015-11-30 stephen.d case []string:
125 4b33cdd0 2015-11-30 stephen.d if err := e.encode(uint16(len(v))); err != nil {
126 4b33cdd0 2015-11-30 stephen.d return err
127 4b33cdd0 2015-11-30 stephen.d }
128 4b33cdd0 2015-11-30 stephen.d
129 4b33cdd0 2015-11-30 stephen.d for _, m := range v {
130 4b33cdd0 2015-11-30 stephen.d if err := e.encode(m); err != nil {
131 4b33cdd0 2015-11-30 stephen.d return err
132 4b33cdd0 2015-11-30 stephen.d }
133 4b33cdd0 2015-11-30 stephen.d }
134 4b33cdd0 2015-11-30 stephen.d case *[]string:
135 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
136 4b33cdd0 2015-11-30 stephen.d return err
137 4b33cdd0 2015-11-30 stephen.d }
138 4b33cdd0 2015-11-30 stephen.d case time.Time:
139 4b33cdd0 2015-11-30 stephen.d if err := e.encode(uint32(v.Unix())); err != nil {
140 4b33cdd0 2015-11-30 stephen.d return err
141 4b33cdd0 2015-11-30 stephen.d }
142 4b33cdd0 2015-11-30 stephen.d case *time.Time:
143 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
144 4b33cdd0 2015-11-30 stephen.d return err
145 4b33cdd0 2015-11-30 stephen.d }
146 4b33cdd0 2015-11-30 stephen.d case Qid:
147 4b33cdd0 2015-11-30 stephen.d if err := e.encode(v.Type, v.Version, v.Path); err != nil {
148 4b33cdd0 2015-11-30 stephen.d return err
149 4b33cdd0 2015-11-30 stephen.d }
150 4b33cdd0 2015-11-30 stephen.d case *Qid:
151 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
152 4b33cdd0 2015-11-30 stephen.d return err
153 4b33cdd0 2015-11-30 stephen.d }
154 4b33cdd0 2015-11-30 stephen.d case []Qid:
155 4b33cdd0 2015-11-30 stephen.d if err := e.encode(uint16(len(v))); err != nil {
156 4b33cdd0 2015-11-30 stephen.d return err
157 4b33cdd0 2015-11-30 stephen.d }
158 4b33cdd0 2015-11-30 stephen.d
159 4b33cdd0 2015-11-30 stephen.d elements := make([]interface{}, len(v))
160 4b33cdd0 2015-11-30 stephen.d for i := range v {
161 4b33cdd0 2015-11-30 stephen.d elements[i] = &v[i]
162 4b33cdd0 2015-11-30 stephen.d }
163 4b33cdd0 2015-11-30 stephen.d
164 4b33cdd0 2015-11-30 stephen.d if err := e.encode(elements...); err != nil {
165 4b33cdd0 2015-11-30 stephen.d return err
166 4b33cdd0 2015-11-30 stephen.d }
167 4b33cdd0 2015-11-30 stephen.d case *[]Qid:
168 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
169 4b33cdd0 2015-11-30 stephen.d return err
170 4b33cdd0 2015-11-30 stephen.d }
171 4b33cdd0 2015-11-30 stephen.d case Dir:
172 4b33cdd0 2015-11-30 stephen.d elements, err := fields9p(v)
173 4b33cdd0 2015-11-30 stephen.d if err != nil {
174 4b33cdd0 2015-11-30 stephen.d return err
175 4b33cdd0 2015-11-30 stephen.d }
176 4b33cdd0 2015-11-30 stephen.d
177 4b33cdd0 2015-11-30 stephen.d if err := e.encode(uint16(size9p(elements...))); err != nil {
178 4b33cdd0 2015-11-30 stephen.d return err
179 4b33cdd0 2015-11-30 stephen.d }
180 4b33cdd0 2015-11-30 stephen.d
181 4b33cdd0 2015-11-30 stephen.d if err := e.encode(elements...); err != nil {
182 4b33cdd0 2015-11-30 stephen.d return err
183 4b33cdd0 2015-11-30 stephen.d }
184 4b33cdd0 2015-11-30 stephen.d case *Dir:
185 961194b3 2015-12-04 stevvooe if err := e.encode(*v); err != nil {
186 961194b3 2015-12-04 stevvooe return err
187 961194b3 2015-12-04 stevvooe }
188 961194b3 2015-12-04 stevvooe case []Dir:
189 961194b3 2015-12-04 stevvooe elements := make([]interface{}, len(v))
190 961194b3 2015-12-04 stevvooe for i := range v {
191 961194b3 2015-12-04 stevvooe elements[i] = &v[i]
192 961194b3 2015-12-04 stevvooe }
193 961194b3 2015-12-04 stevvooe
194 961194b3 2015-12-04 stevvooe if err := e.encode(elements...); err != nil {
195 961194b3 2015-12-04 stevvooe return err
196 961194b3 2015-12-04 stevvooe }
197 961194b3 2015-12-04 stevvooe case *[]Dir:
198 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
199 4b33cdd0 2015-11-30 stephen.d return err
200 4b33cdd0 2015-11-30 stephen.d }
201 4b33cdd0 2015-11-30 stephen.d case Fcall:
202 4b33cdd0 2015-11-30 stephen.d if err := e.encode(v.Type, v.Tag, v.Message); err != nil {
203 4b33cdd0 2015-11-30 stephen.d return err
204 4b33cdd0 2015-11-30 stephen.d }
205 4b33cdd0 2015-11-30 stephen.d case *Fcall:
206 4b33cdd0 2015-11-30 stephen.d if err := e.encode(*v); err != nil {
207 4b33cdd0 2015-11-30 stephen.d return err
208 4b33cdd0 2015-11-30 stephen.d }
209 4b33cdd0 2015-11-30 stephen.d case Message:
210 4b33cdd0 2015-11-30 stephen.d elements, err := fields9p(v)
211 4b33cdd0 2015-11-30 stephen.d if err != nil {
212 4b33cdd0 2015-11-30 stephen.d return err
213 4b33cdd0 2015-11-30 stephen.d }
214 4b33cdd0 2015-11-30 stephen.d
215 4b33cdd0 2015-11-30 stephen.d switch v.(type) {
216 4b33cdd0 2015-11-30 stephen.d case MessageRstat, *MessageRstat:
217 4b33cdd0 2015-11-30 stephen.d // NOTE(stevvooe): Prepend size preceeding Dir. See bugs in
218 4b33cdd0 2015-11-30 stephen.d // http://man.cat-v.org/plan_9/5/stat to make sense of this.
219 4b33cdd0 2015-11-30 stephen.d // The field has been included here but we need to make sure
220 4b33cdd0 2015-11-30 stephen.d // to double emit it for Rstat.
221 4b33cdd0 2015-11-30 stephen.d if err := e.encode(uint16(size9p(elements...))); err != nil {
222 4b33cdd0 2015-11-30 stephen.d return err
223 4b33cdd0 2015-11-30 stephen.d }
224 4b33cdd0 2015-11-30 stephen.d }
225 4b33cdd0 2015-11-30 stephen.d
226 4b33cdd0 2015-11-30 stephen.d if err := e.encode(elements...); err != nil {
227 4b33cdd0 2015-11-30 stephen.d return err
228 4b33cdd0 2015-11-30 stephen.d }
229 4b33cdd0 2015-11-30 stephen.d }
230 4b33cdd0 2015-11-30 stephen.d }
231 4b33cdd0 2015-11-30 stephen.d
232 4b33cdd0 2015-11-30 stephen.d return nil
233 4b33cdd0 2015-11-30 stephen.d }
234 4b33cdd0 2015-11-30 stephen.d
235 4b33cdd0 2015-11-30 stephen.d type decoder struct {
236 4b33cdd0 2015-11-30 stephen.d rd io.Reader
237 4b33cdd0 2015-11-30 stephen.d }
238 4b33cdd0 2015-11-30 stephen.d
239 4b33cdd0 2015-11-30 stephen.d // read9p extracts values from rd and unmarshals them to the targets of vs.
240 4b33cdd0 2015-11-30 stephen.d func (d *decoder) decode(vs ...interface{}) error {
241 4b33cdd0 2015-11-30 stephen.d for _, v := range vs {
242 4b33cdd0 2015-11-30 stephen.d switch v := v.(type) {
243 4b33cdd0 2015-11-30 stephen.d case *uint8, *uint16, *uint32, *uint64, *FcallType, *Tag, *QType, *Fid, *Flag:
244 4b33cdd0 2015-11-30 stephen.d if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
245 4b33cdd0 2015-11-30 stephen.d return err
246 4b33cdd0 2015-11-30 stephen.d }
247 4b33cdd0 2015-11-30 stephen.d case *[]byte:
248 4b33cdd0 2015-11-30 stephen.d var ll uint32
249 4b33cdd0 2015-11-30 stephen.d
250 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&ll); err != nil {
251 4b33cdd0 2015-11-30 stephen.d return err
252 4b33cdd0 2015-11-30 stephen.d }
253 4b33cdd0 2015-11-30 stephen.d
254 15c991ff 2016-11-16 noreply if ll > 0 {
255 15c991ff 2016-11-16 noreply *v = make([]byte, int(ll))
256 15c991ff 2016-11-16 noreply }
257 4b33cdd0 2015-11-30 stephen.d
258 4b33cdd0 2015-11-30 stephen.d if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
259 4b33cdd0 2015-11-30 stephen.d return err
260 4b33cdd0 2015-11-30 stephen.d }
261 4b33cdd0 2015-11-30 stephen.d case *string:
262 4b33cdd0 2015-11-30 stephen.d var ll uint16
263 4b33cdd0 2015-11-30 stephen.d
264 4b33cdd0 2015-11-30 stephen.d // implement string[s] encoding
265 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&ll); err != nil {
266 4b33cdd0 2015-11-30 stephen.d return err
267 4b33cdd0 2015-11-30 stephen.d }
268 4b33cdd0 2015-11-30 stephen.d
269 4b33cdd0 2015-11-30 stephen.d b := make([]byte, ll)
270 4b33cdd0 2015-11-30 stephen.d
271 4b33cdd0 2015-11-30 stephen.d n, err := io.ReadFull(d.rd, b)
272 4b33cdd0 2015-11-30 stephen.d if err != nil {
273 4b33cdd0 2015-11-30 stephen.d return err
274 4b33cdd0 2015-11-30 stephen.d }
275 4b33cdd0 2015-11-30 stephen.d
276 4b33cdd0 2015-11-30 stephen.d if n != int(ll) {
277 4b33cdd0 2015-11-30 stephen.d return fmt.Errorf("unexpected string length")
278 4b33cdd0 2015-11-30 stephen.d }
279 4b33cdd0 2015-11-30 stephen.d
280 4b33cdd0 2015-11-30 stephen.d *v = string(b)
281 4b33cdd0 2015-11-30 stephen.d case *[]string:
282 4b33cdd0 2015-11-30 stephen.d var ll uint16
283 4b33cdd0 2015-11-30 stephen.d
284 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&ll); err != nil {
285 4b33cdd0 2015-11-30 stephen.d return err
286 4b33cdd0 2015-11-30 stephen.d }
287 4b33cdd0 2015-11-30 stephen.d
288 4b33cdd0 2015-11-30 stephen.d elements := make([]interface{}, int(ll))
289 4b33cdd0 2015-11-30 stephen.d *v = make([]string, int(ll))
290 4b33cdd0 2015-11-30 stephen.d for i := range elements {
291 4b33cdd0 2015-11-30 stephen.d elements[i] = &(*v)[i]
292 4b33cdd0 2015-11-30 stephen.d }
293 4b33cdd0 2015-11-30 stephen.d
294 4b33cdd0 2015-11-30 stephen.d if err := d.decode(elements...); err != nil {
295 4b33cdd0 2015-11-30 stephen.d return err
296 4b33cdd0 2015-11-30 stephen.d }
297 4b33cdd0 2015-11-30 stephen.d case *time.Time:
298 4b33cdd0 2015-11-30 stephen.d var epoch uint32
299 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&epoch); err != nil {
300 4b33cdd0 2015-11-30 stephen.d return err
301 4b33cdd0 2015-11-30 stephen.d }
302 4b33cdd0 2015-11-30 stephen.d
303 4b33cdd0 2015-11-30 stephen.d *v = time.Unix(int64(epoch), 0).UTC()
304 4b33cdd0 2015-11-30 stephen.d case *Qid:
305 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&v.Type, &v.Version, &v.Path); err != nil {
306 4b33cdd0 2015-11-30 stephen.d return err
307 4b33cdd0 2015-11-30 stephen.d }
308 4b33cdd0 2015-11-30 stephen.d case *[]Qid:
309 4b33cdd0 2015-11-30 stephen.d var ll uint16
310 4b33cdd0 2015-11-30 stephen.d
311 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&ll); err != nil {
312 4b33cdd0 2015-11-30 stephen.d return err
313 4b33cdd0 2015-11-30 stephen.d }
314 4b33cdd0 2015-11-30 stephen.d
315 4b33cdd0 2015-11-30 stephen.d elements := make([]interface{}, int(ll))
316 4b33cdd0 2015-11-30 stephen.d *v = make([]Qid, int(ll))
317 4b33cdd0 2015-11-30 stephen.d for i := range elements {
318 4b33cdd0 2015-11-30 stephen.d elements[i] = &(*v)[i]
319 4b33cdd0 2015-11-30 stephen.d }
320 4b33cdd0 2015-11-30 stephen.d
321 4b33cdd0 2015-11-30 stephen.d if err := d.decode(elements...); err != nil {
322 4b33cdd0 2015-11-30 stephen.d return err
323 4b33cdd0 2015-11-30 stephen.d }
324 4b33cdd0 2015-11-30 stephen.d case *Dir:
325 4b33cdd0 2015-11-30 stephen.d var ll uint16
326 4b33cdd0 2015-11-30 stephen.d
327 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&ll); err != nil {
328 4b33cdd0 2015-11-30 stephen.d return err
329 4b33cdd0 2015-11-30 stephen.d }
330 4b33cdd0 2015-11-30 stephen.d
331 4b33cdd0 2015-11-30 stephen.d b := make([]byte, ll)
332 4b33cdd0 2015-11-30 stephen.d // must consume entire dir entry.
333 4b33cdd0 2015-11-30 stephen.d n, err := io.ReadFull(d.rd, b)
334 4b33cdd0 2015-11-30 stephen.d if err != nil {
335 4b33cdd0 2015-11-30 stephen.d log.Println("dir readfull failed:", err, ll, n)
336 4b33cdd0 2015-11-30 stephen.d return err
337 4b33cdd0 2015-11-30 stephen.d }
338 4b33cdd0 2015-11-30 stephen.d
339 4b33cdd0 2015-11-30 stephen.d elements, err := fields9p(v)
340 4b33cdd0 2015-11-30 stephen.d if err != nil {
341 4b33cdd0 2015-11-30 stephen.d return err
342 4b33cdd0 2015-11-30 stephen.d }
343 4b33cdd0 2015-11-30 stephen.d
344 4b33cdd0 2015-11-30 stephen.d dec := &decoder{bytes.NewReader(b)}
345 4b33cdd0 2015-11-30 stephen.d
346 4b33cdd0 2015-11-30 stephen.d if err := dec.decode(elements...); err != nil {
347 4b33cdd0 2015-11-30 stephen.d return err
348 4b33cdd0 2015-11-30 stephen.d }
349 961194b3 2015-12-04 stevvooe case *[]Dir:
350 961194b3 2015-12-04 stevvooe *v = make([]Dir, 0)
351 961194b3 2015-12-04 stevvooe for {
352 961194b3 2015-12-04 stevvooe element := Dir{}
353 961194b3 2015-12-04 stevvooe if err := d.decode(&element); err != nil {
354 961194b3 2015-12-04 stevvooe if err == io.EOF {
355 961194b3 2015-12-04 stevvooe return nil
356 961194b3 2015-12-04 stevvooe }
357 961194b3 2015-12-04 stevvooe return err
358 961194b3 2015-12-04 stevvooe }
359 961194b3 2015-12-04 stevvooe *v = append(*v, element)
360 961194b3 2015-12-04 stevvooe }
361 4b33cdd0 2015-11-30 stephen.d case *Fcall:
362 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&v.Type, &v.Tag); err != nil {
363 4b33cdd0 2015-11-30 stephen.d return err
364 4b33cdd0 2015-11-30 stephen.d }
365 4b33cdd0 2015-11-30 stephen.d
366 4b33cdd0 2015-11-30 stephen.d message, err := newMessage(v.Type)
367 4b33cdd0 2015-11-30 stephen.d if err != nil {
368 4b33cdd0 2015-11-30 stephen.d return err
369 4b33cdd0 2015-11-30 stephen.d }
370 4b33cdd0 2015-11-30 stephen.d
371 4b33cdd0 2015-11-30 stephen.d // NOTE(stevvooe): We do a little pointer dance to allocate the
372 4b33cdd0 2015-11-30 stephen.d // new type, write to it, then assign it back to the interface as
373 4b33cdd0 2015-11-30 stephen.d // a concrete type, avoiding a pointer (the interface) to a
374 4b33cdd0 2015-11-30 stephen.d // pointer.
375 4b33cdd0 2015-11-30 stephen.d rv := reflect.New(reflect.TypeOf(message))
376 4b33cdd0 2015-11-30 stephen.d if err := d.decode(rv.Interface()); err != nil {
377 4b33cdd0 2015-11-30 stephen.d return err
378 4b33cdd0 2015-11-30 stephen.d }
379 4b33cdd0 2015-11-30 stephen.d
380 4b33cdd0 2015-11-30 stephen.d v.Message = rv.Elem().Interface().(Message)
381 4b33cdd0 2015-11-30 stephen.d case Message:
382 4b33cdd0 2015-11-30 stephen.d elements, err := fields9p(v)
383 4b33cdd0 2015-11-30 stephen.d if err != nil {
384 4b33cdd0 2015-11-30 stephen.d return err
385 4b33cdd0 2015-11-30 stephen.d }
386 4b33cdd0 2015-11-30 stephen.d
387 4b33cdd0 2015-11-30 stephen.d switch v.(type) {
388 4b33cdd0 2015-11-30 stephen.d case *MessageRstat, MessageRstat:
389 4b33cdd0 2015-11-30 stephen.d // NOTE(stevvooe): Consume extra size preceeding Dir. See bugs
390 4b33cdd0 2015-11-30 stephen.d // in http://man.cat-v.org/plan_9/5/stat to make sense of
391 4b33cdd0 2015-11-30 stephen.d // this. The field has been included here but we need to make
392 4b33cdd0 2015-11-30 stephen.d // sure to double emit it for Rstat. decode extra size header
393 4b33cdd0 2015-11-30 stephen.d // for stat structure.
394 4b33cdd0 2015-11-30 stephen.d var ll uint16
395 4b33cdd0 2015-11-30 stephen.d if err := d.decode(&ll); err != nil {
396 4b33cdd0 2015-11-30 stephen.d return err
397 4b33cdd0 2015-11-30 stephen.d }
398 4b33cdd0 2015-11-30 stephen.d }
399 4b33cdd0 2015-11-30 stephen.d
400 4b33cdd0 2015-11-30 stephen.d if err := d.decode(elements...); err != nil {
401 4b33cdd0 2015-11-30 stephen.d return err
402 4b33cdd0 2015-11-30 stephen.d }
403 4b33cdd0 2015-11-30 stephen.d }
404 4b33cdd0 2015-11-30 stephen.d }
405 4b33cdd0 2015-11-30 stephen.d
406 4b33cdd0 2015-11-30 stephen.d return nil
407 4b33cdd0 2015-11-30 stephen.d }
408 4b33cdd0 2015-11-30 stephen.d
409 4b33cdd0 2015-11-30 stephen.d // size9p calculates the projected size of the values in vs when encoded into
410 4b33cdd0 2015-11-30 stephen.d // 9p binary protocol. If an element or elements are not valid for 9p encoded,
411 4b33cdd0 2015-11-30 stephen.d // the value 0 will be used for the size. The error will be detected when
412 4b33cdd0 2015-11-30 stephen.d // encoding.
413 4b33cdd0 2015-11-30 stephen.d func size9p(vs ...interface{}) uint32 {
414 4b33cdd0 2015-11-30 stephen.d var s uint32
415 4b33cdd0 2015-11-30 stephen.d for _, v := range vs {
416 4b33cdd0 2015-11-30 stephen.d if v == nil {
417 4b33cdd0 2015-11-30 stephen.d continue
418 4b33cdd0 2015-11-30 stephen.d }
419 4b33cdd0 2015-11-30 stephen.d
420 4b33cdd0 2015-11-30 stephen.d switch v := v.(type) {
421 4b33cdd0 2015-11-30 stephen.d case uint8, uint16, uint32, uint64, FcallType, Tag, QType, Fid, Flag,
422 4b33cdd0 2015-11-30 stephen.d *uint8, *uint16, *uint32, *uint64, *FcallType, *Tag, *QType, *Fid, *Flag:
423 4b33cdd0 2015-11-30 stephen.d s += uint32(binary.Size(v))
424 4b33cdd0 2015-11-30 stephen.d case []byte:
425 4b33cdd0 2015-11-30 stephen.d s += uint32(binary.Size(uint32(0)) + len(v))
426 4b33cdd0 2015-11-30 stephen.d case *[]byte:
427 4b33cdd0 2015-11-30 stephen.d s += size9p(uint32(0), *v)
428 4b33cdd0 2015-11-30 stephen.d case string:
429 4b33cdd0 2015-11-30 stephen.d s += uint32(binary.Size(uint16(0)) + len(v))
430 4b33cdd0 2015-11-30 stephen.d case *string:
431 4b33cdd0 2015-11-30 stephen.d s += size9p(*v)
432 4b33cdd0 2015-11-30 stephen.d case []string:
433 4b33cdd0 2015-11-30 stephen.d s += size9p(uint16(0))
434 4b33cdd0 2015-11-30 stephen.d
435 4b33cdd0 2015-11-30 stephen.d for _, sv := range v {
436 4b33cdd0 2015-11-30 stephen.d s += size9p(sv)
437 4b33cdd0 2015-11-30 stephen.d }
438 4b33cdd0 2015-11-30 stephen.d case *[]string:
439 4b33cdd0 2015-11-30 stephen.d s += size9p(*v)
440 4b33cdd0 2015-11-30 stephen.d case time.Time, *time.Time:
441 4b33cdd0 2015-11-30 stephen.d // BUG(stevvooe): Y2038 is coming.
442 4b33cdd0 2015-11-30 stephen.d s += size9p(uint32(0))
443 4b33cdd0 2015-11-30 stephen.d case Qid:
444 4b33cdd0 2015-11-30 stephen.d s += size9p(v.Type, v.Version, v.Path)
445 4b33cdd0 2015-11-30 stephen.d case *Qid:
446 4b33cdd0 2015-11-30 stephen.d s += size9p(*v)
447 4b33cdd0 2015-11-30 stephen.d case []Qid:
448 4b33cdd0 2015-11-30 stephen.d s += size9p(uint16(0))
449 4b33cdd0 2015-11-30 stephen.d elements := make([]interface{}, len(v))
450 4b33cdd0 2015-11-30 stephen.d for i := range elements {
451 4b33cdd0 2015-11-30 stephen.d elements[i] = &v[i]
452 4b33cdd0 2015-11-30 stephen.d }
453 4b33cdd0 2015-11-30 stephen.d s += size9p(elements...)
454 4b33cdd0 2015-11-30 stephen.d case *[]Qid:
455 4b33cdd0 2015-11-30 stephen.d s += size9p(*v)
456 4b33cdd0 2015-11-30 stephen.d
457 4b33cdd0 2015-11-30 stephen.d case Dir:
458 4b33cdd0 2015-11-30 stephen.d // walk the fields of the message to get the total size. we just
459 4b33cdd0 2015-11-30 stephen.d // use the field order from the message struct. We may add tag
460 4b33cdd0 2015-11-30 stephen.d // ignoring if needed.
461 4b33cdd0 2015-11-30 stephen.d elements, err := fields9p(v)
462 4b33cdd0 2015-11-30 stephen.d if err != nil {
463 4b33cdd0 2015-11-30 stephen.d // BUG(stevvooe): The options here are to return 0, panic or
464 4b33cdd0 2015-11-30 stephen.d // make this return an error. Ideally, we make it safe to
465 4b33cdd0 2015-11-30 stephen.d // return 0 and have the rest of the package do the right
466 4b33cdd0 2015-11-30 stephen.d // thing. For now, we do this, but may want to panic until
467 4b33cdd0 2015-11-30 stephen.d // things are stable.
468 4b33cdd0 2015-11-30 stephen.d panic(err)
469 4b33cdd0 2015-11-30 stephen.d }
470 4b33cdd0 2015-11-30 stephen.d
471 4b33cdd0 2015-11-30 stephen.d s += size9p(elements...) + size9p(uint16(0))
472 4b33cdd0 2015-11-30 stephen.d case *Dir:
473 4b33cdd0 2015-11-30 stephen.d s += size9p(*v)
474 961194b3 2015-12-04 stevvooe case []Dir:
475 961194b3 2015-12-04 stevvooe elements := make([]interface{}, len(v))
476 961194b3 2015-12-04 stevvooe for i := range elements {
477 961194b3 2015-12-04 stevvooe elements[i] = &v[i]
478 961194b3 2015-12-04 stevvooe }
479 961194b3 2015-12-04 stevvooe s += size9p(elements...)
480 961194b3 2015-12-04 stevvooe case *[]Dir:
481 961194b3 2015-12-04 stevvooe s += size9p(*v)
482 4b33cdd0 2015-11-30 stephen.d case Fcall:
483 4b33cdd0 2015-11-30 stephen.d s += size9p(v.Type, v.Tag, v.Message)
484 4b33cdd0 2015-11-30 stephen.d case *Fcall:
485 4b33cdd0 2015-11-30 stephen.d s += size9p(*v)
486 4b33cdd0 2015-11-30 stephen.d case Message:
487 4b33cdd0 2015-11-30 stephen.d // special case twstat and rstat for size fields. See bugs in
488 4b33cdd0 2015-11-30 stephen.d // http://man.cat-v.org/plan_9/5/stat to make sense of this.
489 4b33cdd0 2015-11-30 stephen.d switch v.(type) {
490 4b33cdd0 2015-11-30 stephen.d case *MessageRstat, MessageRstat:
491 4b33cdd0 2015-11-30 stephen.d s += size9p(uint16(0)) // for extra size field before dir
492 4b33cdd0 2015-11-30 stephen.d }
493 4b33cdd0 2015-11-30 stephen.d
494 4b33cdd0 2015-11-30 stephen.d // walk the fields of the message to get the total size. we just
495 4b33cdd0 2015-11-30 stephen.d // use the field order from the message struct. We may add tag
496 4b33cdd0 2015-11-30 stephen.d // ignoring if needed.
497 4b33cdd0 2015-11-30 stephen.d elements, err := fields9p(v)
498 4b33cdd0 2015-11-30 stephen.d if err != nil {
499 4b33cdd0 2015-11-30 stephen.d // BUG(stevvooe): The options here are to return 0, panic or
500 4b33cdd0 2015-11-30 stephen.d // make this return an error. Ideally, we make it safe to
501 4b33cdd0 2015-11-30 stephen.d // return 0 and have the rest of the package do the right
502 4b33cdd0 2015-11-30 stephen.d // thing. For now, we do this, but may want to panic until
503 4b33cdd0 2015-11-30 stephen.d // things are stable.
504 4b33cdd0 2015-11-30 stephen.d panic(err)
505 4b33cdd0 2015-11-30 stephen.d }
506 4b33cdd0 2015-11-30 stephen.d
507 4b33cdd0 2015-11-30 stephen.d s += size9p(elements...)
508 4b33cdd0 2015-11-30 stephen.d }
509 4b33cdd0 2015-11-30 stephen.d }
510 4b33cdd0 2015-11-30 stephen.d
511 4b33cdd0 2015-11-30 stephen.d return s
512 4b33cdd0 2015-11-30 stephen.d }
513 4b33cdd0 2015-11-30 stephen.d
514 4b33cdd0 2015-11-30 stephen.d // fields9p lists the settable fields from a struct type for reading and
515 4b33cdd0 2015-11-30 stephen.d // writing. We are using a lot of reflection here for fairly static
516 4b33cdd0 2015-11-30 stephen.d // serialization but we can replace this in the future with generated code if
517 4b33cdd0 2015-11-30 stephen.d // performance is an issue.
518 4b33cdd0 2015-11-30 stephen.d func fields9p(v interface{}) ([]interface{}, error) {
519 4b33cdd0 2015-11-30 stephen.d rv := reflect.Indirect(reflect.ValueOf(v))
520 4b33cdd0 2015-11-30 stephen.d
521 4b33cdd0 2015-11-30 stephen.d if rv.Kind() != reflect.Struct {
522 4b33cdd0 2015-11-30 stephen.d return nil, fmt.Errorf("cannot extract fields from non-struct: %v", rv)
523 4b33cdd0 2015-11-30 stephen.d }
524 4b33cdd0 2015-11-30 stephen.d
525 4b33cdd0 2015-11-30 stephen.d var elements []interface{}
526 4b33cdd0 2015-11-30 stephen.d for i := 0; i < rv.NumField(); i++ {
527 4b33cdd0 2015-11-30 stephen.d f := rv.Field(i)
528 4b33cdd0 2015-11-30 stephen.d
529 4b33cdd0 2015-11-30 stephen.d if !f.CanInterface() {
530 4b33cdd0 2015-11-30 stephen.d // unexported field, skip it.
531 4b33cdd0 2015-11-30 stephen.d continue
532 4b33cdd0 2015-11-30 stephen.d }
533 4b33cdd0 2015-11-30 stephen.d
534 4b33cdd0 2015-11-30 stephen.d if f.CanAddr() {
535 4b33cdd0 2015-11-30 stephen.d f = f.Addr()
536 4b33cdd0 2015-11-30 stephen.d }
537 4b33cdd0 2015-11-30 stephen.d
538 4b33cdd0 2015-11-30 stephen.d elements = append(elements, f.Interface())
539 4b33cdd0 2015-11-30 stephen.d }
540 4b33cdd0 2015-11-30 stephen.d
541 4b33cdd0 2015-11-30 stephen.d return elements, nil
542 4b33cdd0 2015-11-30 stephen.d }
543 4b33cdd0 2015-11-30 stephen.d
544 4b33cdd0 2015-11-30 stephen.d func string9p(v interface{}) string {
545 4b33cdd0 2015-11-30 stephen.d if v == nil {
546 4b33cdd0 2015-11-30 stephen.d return "nil"
547 4b33cdd0 2015-11-30 stephen.d }
548 4b33cdd0 2015-11-30 stephen.d
549 4b33cdd0 2015-11-30 stephen.d rv := reflect.Indirect(reflect.ValueOf(v))
550 4b33cdd0 2015-11-30 stephen.d
551 4b33cdd0 2015-11-30 stephen.d if rv.Kind() != reflect.Struct {
552 4b33cdd0 2015-11-30 stephen.d panic("not a struct")
553 4b33cdd0 2015-11-30 stephen.d }
554 4b33cdd0 2015-11-30 stephen.d
555 4b33cdd0 2015-11-30 stephen.d var s string
556 4b33cdd0 2015-11-30 stephen.d
557 4b33cdd0 2015-11-30 stephen.d for i := 0; i < rv.NumField(); i++ {
558 4b33cdd0 2015-11-30 stephen.d f := rv.Field(i)
559 4b33cdd0 2015-11-30 stephen.d
560 4b33cdd0 2015-11-30 stephen.d s += fmt.Sprintf(" %v=%v", strings.ToLower(rv.Type().Field(i).Name), f.Interface())
561 4b33cdd0 2015-11-30 stephen.d }
562 4b33cdd0 2015-11-30 stephen.d
563 4b33cdd0 2015-11-30 stephen.d return s
564 4b33cdd0 2015-11-30 stephen.d }