commit e9f5e41480fec822e81050643644fd58a98ac861 from: Stephen J Day date: Tue Oct 27 05:11:22 2015 UTC fs/p9p/new: Add message definitions and support Signed-off-by: Stephen J Day commit - 499f8c59005e11c0b5590adabe8b660c4a4cf1cb commit + e9f5e41480fec822e81050643644fd58a98ac861 blob - 081bacb99c65174f24ce8108cfa6eebc7219e27e blob + f1889d8ce531e8e636d504b713ea89ca3146a979 --- encoding.go +++ encoding.go @@ -17,6 +17,23 @@ type encoder struct { 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 @@ -73,7 +90,7 @@ func (d *decoder) decode(vs ...interface{}) error { 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 } @@ -89,6 +106,22 @@ func (d *decoder) decode(vs ...interface{}) error { } *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 { @@ -139,6 +172,16 @@ func size9p(vs ...interface{}) uint32 { 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 @@ -150,18 +193,14 @@ func size9p(vs ...interface{}) uint32 { // 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 @@ -18,6 +18,15 @@ func TestEncodeDecode(t *testing.T) { 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, @@ -27,14 +36,43 @@ func TestEncodeDecode(t *testing.T) { 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} @@ -58,7 +96,7 @@ func TestEncodeDecode(t *testing.T) { } if err := dec.decode(v); err != nil { - fatalf("error reading fcall: %v", err) + fatalf("error reading: %v", err) } if targetType.Kind() != reflect.Ptr { @@ -68,5 +106,7 @@ func TestEncodeDecode(t *testing.T) { 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 @@ -146,9 +146,9 @@ func newMessage(typ FcallType) (Message, error) { 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: @@ -200,6 +200,72 @@ func (mv MessageVersion) String() string { 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