Blob


1 package p9p
3 import (
4 "io"
6 "golang.org/x/net/context"
7 )
9 // ReaddirAll reads all the directory entries for the resource fid.
10 func ReaddirAll(session Session, fid Fid) ([]Dir, error) {
11 panic("not implemented")
12 }
14 // Readdir helps one to implement the server-side of Session.Read on
15 // directories.
16 type Readdir struct {
17 nextfn func() (Dir, error)
18 buf *Dir // one-item buffer
19 codec Codec
20 offset int64
21 }
23 func NewReaddir(codec Codec, next func() (Dir, error)) *Readdir {
24 return &Readdir{
25 nextfn: next,
26 codec: codec,
27 }
28 }
30 func NewFixedReaddir(codec Codec, dir []Dir) *Readdir {
31 dirs := make([]Dir, len(dir))
32 copy(dirs, dir) // make our own copy!
34 return NewReaddir(codec,
35 func() (Dir, error) {
36 if len(dirs) == 0 {
37 return Dir{}, io.EOF
38 }
40 d := dirs[0]
41 dirs = dirs[1:]
42 return d, nil
43 })
44 }
46 func (rd *Readdir) Read(ctx context.Context, p []byte, offset int64) (n int, err error) {
47 if rd.offset != offset {
48 return 0, ErrBadoffset
49 }
51 p = p[:0:len(p)]
52 for len(p) < cap(p) {
53 var d Dir
54 if rd.buf != nil {
55 d = *rd.buf
56 rd.buf = nil
57 } else {
58 d, err = rd.nextfn()
59 if err != nil {
60 goto done
61 }
62 }
64 var dp []byte
65 dp, err = rd.codec.Marshal(d)
66 if err != nil {
67 goto done
68 }
70 if len(p)+len(dp) > cap(p) {
71 // will over fill buffer. save item and exit.
72 rd.buf = &d
73 goto done
74 }
76 p = append(p, dp...)
77 }
79 done:
80 if err == io.EOF && len(p) > 0 {
81 // Don't let io.EOF escape if we've written to p. 9p doesn't handle
82 // this like Go.
83 err = nil
84 }
86 rd.offset += int64(len(p))
87 return len(p), err
88 }