commit - 755621adc48bd5d72563edcaa93d627eee0fef24
commit + 7cd259a2e418951032d970bf316a144fda865dc5
blob - /dev/null
blob + b3ab9d195896f7f19afc47915087d68419801816 (mode 644)
--- /dev/null
+++ readdir.go
+package p9pnew
+
+import (
+ "io"
+
+ "golang.org/x/net/context"
+)
+
+// ReaddirAll reads all the directory entries for the resource fid.
+func ReaddirAll(session Session, fid Fid) ([]Dir, error) {
+ panic("not implemented")
+}
+
+// Readdir helps one to implement the server-side of Session.Read on
+// directories.
+type Readdir struct {
+ nextfn func() (Dir, error)
+ buf *Dir // one-item buffer
+ codec Codec
+ offset int64
+}
+
+func NewReaddir(codec Codec, next func() (Dir, error)) *Readdir {
+ return &Readdir{
+ nextfn: next,
+ codec: codec,
+ }
+}
+
+func NewFixedReaddir(codec Codec, dir []Dir) *Readdir {
+ dirs := make([]Dir, len(dir))
+ copy(dirs, dir) // make our own copy!
+
+ return NewReaddir(codec,
+ func() (Dir, error) {
+ if len(dirs) == 0 {
+ return Dir{}, io.EOF
+ }
+
+ d := dirs[0]
+ dirs = dirs[1:]
+ return d, nil
+ })
+}
+
+func (rd *Readdir) Read(ctx context.Context, p []byte, offset int64) (n int, err error) {
+ if rd.offset != offset {
+ return 0, ErrBadoffset
+ }
+
+ p = p[:0:len(p)]
+ for len(p) < cap(p) {
+ var d Dir
+ if rd.buf != nil {
+ d = *rd.buf
+ rd.buf = nil
+ } else {
+ d, err = rd.nextfn()
+ if err != nil {
+ goto done
+ }
+ }
+
+ var dp []byte
+ dp, err = rd.codec.Marshal(d)
+ if err != nil {
+ goto done
+ }
+
+ if len(p)+len(dp) > cap(p) {
+ // will over fill buffer. save item and exit.
+ rd.buf = &d
+ goto done
+ }
+
+ p = append(p, dp...)
+ }
+
+done:
+ if err == io.EOF && len(p) > 0 {
+ // Don't let io.EOF escape if we've written to p. 9p doesn't handle
+ // this like Go.
+ err = nil
+ }
+
+ rd.offset += int64(len(p))
+ return len(p), err
+}