-
Notifications
You must be signed in to change notification settings - Fork 7
/
anchor.go
104 lines (82 loc) · 2.06 KB
/
anchor.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
94
95
96
97
98
99
100
101
102
103
104
package anchor
import (
"context"
"capnproto.org/go/capnp/v3"
api "github.com/wetware/pkg/api/anchor"
"github.com/wetware/pkg/cap/internal/bounded"
)
type Anchor api.Anchor
func (a Anchor) AddRef() Anchor {
return Anchor(api.Anchor(a).AddRef())
}
func (a Anchor) Release() {
capnp.Client(a).Release()
}
func (a Anchor) Ls(ctx context.Context) (*Iterator, capnp.ReleaseFunc) {
f, release := api.Anchor(a).Ls(ctx, nil)
return &Iterator{fut: f}, release
}
// Walk to the register located at path.
func (a Anchor) Walk(ctx context.Context, path string) (Anchor, capnp.ReleaseFunc) {
p := NewPath(path)
if p == (Path{}) {
anchor := a.AddRef()
return anchor, anchor.Release
}
f, release := api.Anchor(a).Walk(ctx, destination(p))
return Anchor(f.Anchor()), release
}
func destination(path Path) func(api.Anchor_walk_Params) error {
return func(ps api.Anchor_walk_Params) error {
return path.bind(func(s string) bounded.Type[string] {
err := ps.SetPath(trimmed(s))
return bounded.Failure[string](err) // can be nil
}).Err()
}
}
type Iterator struct {
fut api.Anchor_ls_Results_Future
err error
// cache
children api.Anchor_Child_List
index int
}
func (it *Iterator) resolve() {
if it.err == nil && it.children == (api.Anchor_Child_List{}) {
var res api.Anchor_ls_Results
if res, it.err = it.fut.Struct(); it.err == nil {
it.children, it.err = res.Children()
}
}
}
func (it *Iterator) Err() error {
select {
case <-it.fut.Done():
it.resolve()
default:
}
return it.err
}
// Next returns the name of the next subanchor in the stream. It
// returns an empty string when the iterator has been exhausted.
func (it *Iterator) Next() (name string) {
if it.children == (api.Anchor_Child_List{}) {
it.resolve()
} else {
it.index++
}
if it.more() {
name, it.err = it.children.At(it.index).Name()
}
return
}
func (it *Iterator) more() bool {
size := it.children.Len()
return it.err == nil && it.index < size
}
func (it *Iterator) Anchor() Anchor {
if it.more() {
return Anchor(it.children.At(it.index).Anchor())
}
return Anchor{}
}