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 {
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 {
29 type Codec interface {
30 Unmarshal(data []byte, v interface{}) error
31 Marshal(data []byte, v interface{}) (n int, err error)
36 func (c codec9p) Unmarshal(data []byte, v interface{}) error {
37 dec := &decoder{bytes.NewReader(data)}
41 func (c codec9p) Marshal(data []byte, v interface{}) (n int, err error) {
44 buf := bytes.NewBuffer(data[:0])
47 if err := enc.encode(v); err != nil {
51 if len(data) < buf.Len() {
52 return len(data), io.ErrShortBuffer
58 // NOTE(stevvooe): This file covers 9p encoding and decoding (despite just
59 // being called encoding).
65 func (e *encoder) encode(vs ...interface{}) error {
66 for _, v := range vs {
67 switch v := v.(type) {
69 if err := e.encode(*v); err != nil {
73 if err := e.encode(uint16(len(v))); err != nil {
77 var elements []interface{}
79 elements = append(elements, e)
82 if err := e.encode(elements...); err != nil {
86 if err := e.encode(uint32(len(*v))); err != nil {
90 if err := e.encode(*v); err != nil {
94 if err := e.encode(*v); err != nil {
98 // implement string[s] encoding
99 if err := binary.Write(e.wr, binary.LittleEndian, uint16(len(v))); err != nil {
103 _, err := io.WriteString(e.wr, v)
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)
117 elements = append([]interface{}{uint16(size9p(elements...))}, elements...)
119 if err := e.encode(elements...); err != nil {
123 elements, err := fields9p(v)
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 {
138 if err := e.encode(*v); err != nil {
142 if err := e.encode(v.Type, v.Version, v.Path); err != nil {
146 if err := e.encode(*v); err != nil {
150 if err := e.encode(uint16(len(v))); err != nil {
154 elements := make([]interface{}, len(v))
159 if err := e.encode(elements...); err != nil {
163 if err := e.encode(uint32(v.Unix())); err != nil {
167 if err := e.encode(*v); err != nil {
171 if err := e.encode(&v); err != nil {
175 if err := e.encode(v.Type, v.Tag, v.Message); err != nil {
179 if err := binary.Write(e.wr, binary.LittleEndian, v); err != nil {
188 type decoder struct {
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) {
199 // implement string[s] encoding
200 if err := d.decode(&ll); err != nil {
204 b := make([]byte, ll)
206 n, err := io.ReadFull(d.rd, b)
208 log.Println("readfull failed:", err, ll, n)
213 return fmt.Errorf("unexpected string length")
220 if err := d.decode(&ll); err != nil {
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 {
236 if err := d.decode(&ll); err != nil {
240 *v = make([]byte, int(ll))
242 if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
246 if err := d.decode(&v.Type, &v.Tag); err != nil {
251 v.Message, err = newMessage(v.Type)
253 log.Printf("unknown message type %#v", v.Type)
257 // take the address of v.Message from the struct and encode into
260 if err := d.decode(v.Message); err != nil {
266 if err := d.decode(&ll); err != nil {
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 {
281 if err := d.decode(&epoch); err != nil {
285 *v = time.Unix(int64(epoch), 0).UTC()
289 if err := d.decode(&ll); err != nil {
293 b := make([]byte, ll)
294 // must consume entire dir entry.
295 n, err := io.ReadFull(d.rd, b)
297 log.Println("dir readfull failed:", err, ll, n)
301 elements, err := fields9p(v)
306 dec := &decoder{bytes.NewReader(b)}
308 if err := dec.decode(elements...); err != nil {
312 elements, err := fields9p(v)
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.
320 case *MessageRstat, MessageRstat:
321 // decode extra size header for stat structure.
323 if err := d.decode(&ll); err != nil {
328 if err := d.decode(elements...); err != nil {
332 if err := d.decode(&v.Type, &v.Version, &v.Path); err != nil {
336 if err := binary.Read(d.rd, binary.LittleEndian, v); err != 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
349 func size9p(vs ...interface{}) uint32 {
351 for _, v := range vs {
356 switch v := v.(type) {
358 s += uint32(binary.Size(uint16(0)) + len(*v))
360 s += uint32(binary.Size(uint16(0)) + len(v))
364 s += size9p(uint16(0))
365 elements := make([]interface{}, len(v))
366 for i := range elements {
370 s += size9p(elements...)
372 s += size9p(uint32(0), *v)
376 s += size9p(uint16(0))
377 elements := make([]interface{}, len(v))
378 for i := range elements {
381 s += size9p(elements...)
382 case time.Time, *time.Time:
383 s += size9p(uint32(0))
385 s += size9p(v.Type, v.Version, v.Path)
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)
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.
400 s += size9p(elements...) + size9p(uint16(0))
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.
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)
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.
423 s += size9p(elements...)
429 s += size9p(v.Type, v.Tag, v.Message)
433 s += uint32(binary.Size(v))
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++ {
455 if !f.CanInterface() {
456 return nil, fmt.Errorf("can't interface: %v", f)
463 elements = append(elements, f.Interface())
469 func string9p(v interface{}) string {
474 rv := reflect.Indirect(reflect.ValueOf(v))
476 if rv.Kind() != reflect.Struct {
477 panic("not a struct")
482 for i := 0; i < rv.NumField(); i++ {
485 s += fmt.Sprintf(" %v=%v", strings.ToLower(rv.Type().Field(i).Name), f.Interface())