This repository has been archived by the owner on Mar 11, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathreaddir.go
93 lines (78 loc) · 1.81 KB
/
readdir.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package p9p
import (
"io"
"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
}
// NewReaddir returns a new Readdir to assist implementing server-side Readdir.
// The codec will be used to decode messages with Dir entries. The provided
// function next will be called until io.EOF is returned.
func NewReaddir(codec Codec, next func() (Dir, error)) *Readdir {
return &Readdir{
nextfn: next,
codec: codec,
}
}
// NewFixedReaddir returns a Readdir that will returned a fixed set of
// directory entries.
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 {
// Don't let io.EOF escape. EOF is indicated by a zero-length result
// with no error.
err = nil
}
rd.offset += int64(len(p))
return len(p), err
}