Blob


1 package p9pnew
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "io"
8 "log"
9 "reflect"
10 "strings"
11 "time"
12 )
14 // EncodeDir is just a helper for encoding directories until we export the
15 // encoder and decoder.
16 func EncodeDir(wr io.Writer, d *Dir) error {
17 enc := &encoder{wr}
19 return enc.encode(d)
20 }
22 // DecodeDir is just a helper for decoding directories until we export the
23 // encoder and decoder.
24 func DecodeDir(rd io.Reader, d *Dir) error {
25 dec := &decoder{rd}
26 return dec.decode(d)
27 }
29 type Codec interface {
30 Unmarshal(data []byte, v interface{}) error
31 Marshal(data []byte, v interface{}) (n int, err error)
32 }
34 type codec9p struct{}
36 func (c codec9p) Unmarshal(data []byte, v interface{}) error {
37 dec := &decoder{bytes.NewReader(data)}
38 return dec.decode(v)
39 }
41 func (c codec9p) Marshal(data []byte, v interface{}) (n int, err error) {
42 n = int(size9p(v))
44 buf := bytes.NewBuffer(data[:0])
45 enc := &encoder{buf}
47 if err := enc.encode(v); err != nil {
48 return buf.Len(), nil
49 }
51 if len(data) < buf.Len() {
52 return len(data), io.ErrShortBuffer
53 }
55 return buf.Len(), nil
56 }
58 // NOTE(stevvooe): This file covers 9p encoding and decoding (despite just
59 // being called encoding).
61 type encoder struct {
62 wr io.Writer
63 }
65 func (e *encoder) encode(vs ...interface{}) error {
66 for _, v := range vs {
67 switch v := v.(type) {
68 case *[]string:
69 if err := e.encode(*v); err != nil {
70 return err
71 }
72 case []string:
73 if err := e.encode(uint16(len(v))); err != nil {
74 return err
75 }
77 var elements []interface{}
78 for _, e := range v {
79 elements = append(elements, e)
80 }
82 if err := e.encode(elements...); err != nil {
83 return err
84 }
85 case *[]byte:
86 if err := e.encode(uint32(len(*v))); err != nil {
87 return err
88 }
90 if err := e.encode(*v); err != nil {
91 return err
92 }
93 case *string:
94 if err := e.encode(*v); err != nil {
95 return err
96 }
97 case string:
98 // implement string[s] encoding
99 if err := binary.Write(e.wr, binary.LittleEndian, uint16(len(v))); err != nil {
100 return err
103 _, err := io.WriteString(e.wr, v)
104 if err != nil {
105 return err
107 case *Dir:
108 // NOTE(stevvooe): See bugs in http://man.cat-v.org/plan_9/5/stat
109 // to make sense of this. The field has been included here but we
110 // need to make sure to double emit it for Rstat.
112 elements, err := fields9p(v)
113 if err != nil {
114 return err
117 elements = append([]interface{}{uint16(size9p(elements...))}, elements...)
119 if err := e.encode(elements...); err != nil {
120 return err
122 case Message:
123 elements, err := fields9p(v)
124 if err != nil {
125 return err
128 switch v.(type) {
129 case MessageRstat, *MessageRstat:
130 // encode an size header in front of the dir field
131 elements = append([]interface{}{uint16(size9p(elements...))}, elements...)
134 if err := e.encode(elements...); err != nil {
135 return err
137 case *Qid:
138 if err := e.encode(*v); err != nil {
139 return err
141 case Qid:
142 if err := e.encode(v.Type, v.Version, v.Path); err != nil {
143 return err
145 case *[]Qid:
146 if err := e.encode(*v); err != nil {
147 return err
149 case []Qid:
150 if err := e.encode(uint16(len(v))); err != nil {
151 return err
154 elements := make([]interface{}, len(v))
155 for i := range v {
156 elements[i] = &v[i]
159 if err := e.encode(elements...); err != nil {
160 return err
162 case time.Time:
163 if err := e.encode(uint32(v.Unix())); err != nil {
164 return err
166 case *time.Time:
167 if err := e.encode(*v); err != nil {
168 return err
170 case Fcall:
171 if err := e.encode(&v); err != nil {
172 return err
174 case *Fcall:
175 if err := e.encode(v.Type, v.Tag, v.Message); err != nil {
176 return err
178 default:
179 if err := binary.Write(e.wr, binary.LittleEndian, v); err != nil {
180 return err
185 return nil
188 type decoder struct {
189 rd io.Reader
192 // read9p extracts values from rd and unmarshals them to the targets of vs.
193 func (d *decoder) decode(vs ...interface{}) error {
194 for _, v := range vs {
195 switch v := v.(type) {
196 case *string:
197 var ll uint16
199 // implement string[s] encoding
200 if err := d.decode(&ll); err != nil {
201 return err
204 b := make([]byte, ll)
206 n, err := io.ReadFull(d.rd, b)
207 if err != nil {
208 log.Println("readfull failed:", err, ll, n)
209 return err
212 if n != int(ll) {
213 return fmt.Errorf("unexpected string length")
216 *v = string(b)
217 case *[]string:
218 var ll uint16
220 if err := d.decode(&ll); err != nil {
221 return err
224 elements := make([]interface{}, int(ll))
225 *v = make([]string, int(ll))
226 for i := range elements {
227 elements[i] = &(*v)[i]
230 if err := d.decode(elements...); err != nil {
231 return err
233 case *[]byte:
234 var ll uint32
236 if err := d.decode(&ll); err != nil {
237 return err
240 *v = make([]byte, int(ll))
242 if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
243 return err
245 case *Fcall:
246 if err := d.decode(&v.Type, &v.Tag); err != nil {
247 return err
250 var err error
251 v.Message, err = newMessage(v.Type)
252 if err != nil {
253 log.Printf("unknown message type %#v", v.Type)
254 return err
257 // take the address of v.Message from the struct and encode into
258 // that.
260 if err := d.decode(v.Message); err != nil {
261 return err
263 case *[]Qid:
264 var ll uint16
266 if err := d.decode(&ll); err != nil {
267 return err
270 elements := make([]interface{}, int(ll))
271 *v = make([]Qid, int(ll))
272 for i := range elements {
273 elements[i] = &(*v)[i]
276 if err := d.decode(elements...); err != nil {
277 return err
279 case *time.Time:
280 var epoch uint32
281 if err := d.decode(&epoch); err != nil {
282 return err
285 *v = time.Unix(int64(epoch), 0).UTC()
286 case *Dir:
287 var ll uint16
289 if err := d.decode(&ll); err != nil {
290 return err
293 b := make([]byte, ll)
294 // must consume entire dir entry.
295 n, err := io.ReadFull(d.rd, b)
296 if err != nil {
297 log.Println("dir readfull failed:", err, ll, n)
298 return err
301 elements, err := fields9p(v)
302 if err != nil {
303 return err
306 dec := &decoder{bytes.NewReader(b)}
308 if err := dec.decode(elements...); err != nil {
309 return err
311 case Message:
312 elements, err := fields9p(v)
313 if err != nil {
314 return err
317 // special case twstat and rstat for size fields. See bugs in
318 // http://man.cat-v.org/plan_9/5/stat to make sense of this.
319 switch v.(type) {
320 case *MessageRstat, MessageRstat:
321 // decode extra size header for stat structure.
322 var ll uint16
323 if err := d.decode(&ll); err != nil {
324 return err
328 if err := d.decode(elements...); err != nil {
329 return err
331 case *Qid:
332 if err := d.decode(&v.Type, &v.Version, &v.Path); err != nil {
333 return err
335 default:
336 if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
337 return err
342 return nil
345 // size9p calculates the projected size of the values in vs when encoded into
346 // 9p binary protocol. If an element or elements are not valid for 9p encoded,
347 // the value 0 will be used for the size. The error will be detected when
348 // encoding.
349 func size9p(vs ...interface{}) uint32 {
350 var s uint32
351 for _, v := range vs {
352 if v == nil {
353 continue
356 switch v := v.(type) {
357 case *string:
358 s += uint32(binary.Size(uint16(0)) + len(*v))
359 case string:
360 s += uint32(binary.Size(uint16(0)) + len(v))
361 case *[]string:
362 s += size9p(*v)
363 case []string:
364 s += size9p(uint16(0))
365 elements := make([]interface{}, len(v))
366 for i := range elements {
367 elements[i] = v[i]
370 s += size9p(elements...)
371 case *[]byte:
372 s += size9p(uint32(0), *v)
373 case *[]Qid:
374 s += size9p(*v)
375 case []Qid:
376 s += size9p(uint16(0))
377 elements := make([]interface{}, len(v))
378 for i := range elements {
379 elements[i] = &v[i]
381 s += size9p(elements...)
382 case time.Time, *time.Time:
383 s += size9p(uint32(0))
384 case Qid:
385 s += size9p(v.Type, v.Version, v.Path)
386 case Dir:
387 // walk the fields of the message to get the total size. we just
388 // use the field order from the message struct. We may add tag
389 // ignoring if needed.
390 elements, err := fields9p(v)
391 if err != nil {
392 // BUG(stevvooe): The options here are to return 0, panic or
393 // make this return an error. Ideally, we make it safe to
394 // return 0 and have the rest of the package do the right
395 // thing. For now, we do this, but may want to panic until
396 // things are stable.
397 panic(err)
400 s += size9p(elements...) + size9p(uint16(0))
401 case Message:
403 // special case twstat and rstat for size fields. See bugs in
404 // http://man.cat-v.org/plan_9/5/stat to make sense of this.
405 switch v.(type) {
406 case *MessageRstat, MessageRstat:
407 s += size9p(uint16(0)) // for extra size field before dir
410 // walk the fields of the message to get the total size. we just
411 // use the field order from the message struct. We may add tag
412 // ignoring if needed.
413 elements, err := fields9p(v)
414 if err != nil {
415 // BUG(stevvooe): The options here are to return 0, panic or
416 // make this return an error. Ideally, we make it safe to
417 // return 0 and have the rest of the package do the right
418 // thing. For now, we do this, but may want to panic until
419 // things are stable.
420 panic(err)
423 s += size9p(elements...)
424 case *Qid:
425 s += size9p(*v)
426 case *Dir:
427 s += size9p(*v)
428 case Fcall:
429 s += size9p(v.Type, v.Tag, v.Message)
430 case *Fcall:
431 s += size9p(*v)
432 default:
433 s += uint32(binary.Size(v))
437 return s
440 // fields9p lists the settable fields from a struct type for reading and
441 // writing. We are using a lot of reflection here for fairly static
442 // serialization but we can replace this in the future with generated code if
443 // performance is an issue.
444 func fields9p(v interface{}) ([]interface{}, error) {
445 rv := reflect.Indirect(reflect.ValueOf(v))
447 if rv.Kind() != reflect.Struct {
448 return nil, fmt.Errorf("cannot extract fields from non-struct: %v", rv)
451 var elements []interface{}
452 for i := 0; i < rv.NumField(); i++ {
453 f := rv.Field(i)
455 if !f.CanInterface() {
456 return nil, fmt.Errorf("can't interface: %v", f)
459 if f.CanAddr() {
460 f = f.Addr()
463 elements = append(elements, f.Interface())
466 return elements, nil
469 func string9p(v interface{}) string {
470 if v == nil {
471 return "nil"
474 rv := reflect.Indirect(reflect.ValueOf(v))
476 if rv.Kind() != reflect.Struct {
477 panic("not a struct")
480 var s string
482 for i := 0; i < rv.NumField(); i++ {
483 f := rv.Field(i)
485 s += fmt.Sprintf(" %v=%v", strings.ToLower(rv.Type().Field(i).Name), f.Interface())
488 return s