commit - 499f8c59005e11c0b5590adabe8b660c4a4cf1cb
commit + e9f5e41480fec822e81050643644fd58a98ac861
blob - 081bacb99c65174f24ce8108cfa6eebc7219e27e
blob + f1889d8ce531e8e636d504b713ea89ca3146a979
--- encoding.go
+++ encoding.go
func (e *encoder) encode(vs ...interface{}) error {
for _, v := range vs {
switch v := v.(type) {
+ case *[]string:
+ if err := e.encode(*v); err != nil {
+ return err
+ }
+ case []string:
+ if err := e.encode(uint16(len(v))); err != nil {
+ return err
+ }
+
+ var elements []interface{}
+ for _, e := range v {
+ elements = append(elements, e)
+ }
+
+ if err := e.encode(elements...); err != nil {
+ return err
+ }
case *string:
if err := e.encode(*v); err != nil {
return err
var ll uint16
// implement string[s] encoding
- if err := binary.Read(d.rd, binary.LittleEndian, &ll); err != nil {
+ if err := d.decode(&ll); err != nil {
return err
}
}
*v = string(b)
+ case *[]string:
+ var ll uint16
+
+ if err := d.decode(&ll); err != nil {
+ return err
+ }
+
+ elements := make([]interface{}, int(ll))
+ *v = make([]string, int(ll))
+ for i := range elements {
+ elements[i] = &(*v)[i]
+ }
+
+ if err := d.decode(elements...); err != nil {
+ return err
+ }
case *Fcall:
var size uint32
if err := d.decode(&size, &v.Type, &v.Tag); err != nil {
s += uint32(binary.Size(uint16(0)) + len(*v))
case string:
s += uint32(binary.Size(uint16(0)) + len(v))
+ case *[]string:
+ s += size9p(*v)
+ case []string:
+ s += size9p(uint16(0))
+ elements := make([]interface{}, len(v))
+ for i := range elements {
+ elements[i] = v[i]
+ }
+
+ s += size9p(elements...)
case Message:
// walk the fields of the message to get the total size. we just
// use the field order from the message struct. We may add tag
// return 0 and have the rest of the package do the right
// thing. For now, we do this, but may want to panic until
// things are stable.
- return 0
+ panic(err)
}
s += size9p(elements...)
case Fcall:
- s += size9p(v.Type, v.Tag, v.Message)
+ s += size9p(uint32(0), v.Type, v.Tag, v.Message)
case *Fcall:
- // Calculates the total size of the fcall, excluding the size
- // header, which is handled exernally. The result of
- // (*Fcall).MarshalBinary will have len(p) == the result of this
- // branch. The value should be
- s += size9p(v.Type, v.Tag, v.Message)
+ s += size9p(*v)
default:
s += uint32(binary.Size(v))
}
blob - 074f520e9f040f5f136f3dec00b7db9a713be4f1
blob + fb38ea4090dfd47997571c4808dcd1bf418408b6
--- encoding_test.go
+++ encoding_test.go
marshaled: []byte{0x4, 0x0, 0x61, 0x73, 0x64, 0x66},
},
{
+ description: "[]string",
+ target: []string{"asdf", "qwer", "zxcv"},
+ marshaled: []byte{
+ 0x3, 0x0, // len(target)
+ 0x4, 0x0, 0x61, 0x73, 0x64, 0x66,
+ 0x4, 0x0, 0x71, 0x77, 0x65, 0x72,
+ 0x4, 0x0, 0x7a, 0x78, 0x63, 0x76},
+ },
+ {
description: "Tversion fcall",
target: &Fcall{
Type: Tversion,
Version: "9PTEST",
},
},
- marshaled: []byte{0xf, 0x0, 0x0, 0x0, 0x64, 0xcf, 0x8, 0x0, 0x4, 0x0, 0x0, 0x6, 0x0, 0x39, 0x50, 0x54, 0x45, 0x53, 0x54},
+ marshaled: []byte{
+ 0x13, 0x0, 0x0, 0x0,
+ 0x64, 0xcf, 0x8, 0x0, 0x4, 0x0, 0x0,
+ 0x6, 0x0, 0x39, 0x50, 0x54, 0x45, 0x53, 0x54},
},
+ {
+ description: "Twalk fcall",
+ target: &Fcall{
+ Type: Twalk,
+ Tag: 5666,
+ Message: &MessageTwalk{
+ Fid: 1010,
+ Newfid: 1011,
+ Wname: []string{"a", "b", "c"},
+ },
+ },
+ marshaled: []byte{
+ 0x1a, 0x0, 0x0, 0x0,
+ 0x6e, 0x22, 0x16, 0xf2, 0x3, 0x0, 0x0, 0xf3, 0x3, 0x0, 0x0,
+ 0x3, 0x0, // len(wnames)
+ 0x1, 0x0, 0x61, // "a"
+ 0x1, 0x0, 0x62, // "b"
+ 0x1, 0x0, 0x63}, // "c"
+ },
} {
t.Logf("target under test: %v", testcase.target)
fatalf := func(format string, args ...interface{}) {
t.Fatalf(testcase.description+": "+format, args...)
}
+ // check that size9p is working correctly
+ if int(size9p(testcase.target)) != len(testcase.marshaled) {
+ fatalf("size not correct: %v != %v", int(size9p(testcase.target)), len(testcase.marshaled))
+ }
+
+ t.Logf("expecting message of %v bytes", len(testcase.marshaled))
+
var b bytes.Buffer
enc := &encoder{&b}
}
if err := dec.decode(v); err != nil {
- fatalf("error reading fcall: %v", err)
+ fatalf("error reading: %v", err)
}
if targetType.Kind() != reflect.Ptr {
if !reflect.DeepEqual(v, testcase.target) {
fatalf("not equal: %#v != %#v", v, testcase.target)
}
+ t.Logf("%#v", v)
+
}
}
blob - d550f4532b8a7fa29594fd215f549c129367981e
blob + 9cb51454c9c0fd95c63d2083b8bbf90ce6cc2db5
--- fcall.go
+++ fcall.go
case Rflush:
return nil, nil // No message body for this response.
case Twalk:
-
+ return &MessageTwalk{}, nil
case Rwalk:
-
+ return &MessageRwalk{}, nil
case Topen:
case Ropen:
return fmt.Sprintf("msize=%v version=%v", mv.MSize, mv.Version)
}
+type MessageTAuth struct {
+ Afid Fid
+ Uname string
+ Aname string
+}
+
+type MessageRAuth struct {
+ Qid Qid
+}
+
+type MessageError struct {
+ Ename string
+}
+
+type MessageTattach struct {
+ Fid Fid
+ Afid Fid
+ Uname string
+ Aname string
+}
+
+type MessageRattach struct {
+ Qid Qid
+}
+
+type MessageTwalk struct {
+ Fid Fid
+ Newfid Fid
+ Wname []string
+}
+
+func (MessageTwalk) message9p() {}
+
+type MessageRwalk struct {
+ Qid []Qid
+}
+
+func (MessageRwalk) message9p() {}
+
+type MessageTopen struct {
+ Fid Fid
+ Mode uint8
+}
+
+type MessageRopen struct {
+ Qid Qid
+ Msize uint32
+}
+
+type MessageTcreate struct {
+ Fid Fid
+ Name string
+ Perm uint32
+ Mode uint8
+}
+
+type MessageTread struct {
+ Fid Fid
+ Offset uint64
+ Count uint32
+}
+
+type MessageRread struct {
+ Data []byte
+}
+
// MessageFlush handles the content for the Tflush message type.
type MessageFlush struct {
Oldtag Tag