-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathiterator.go
79 lines (65 loc) · 1.69 KB
/
iterator.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
package orchestrator
import (
"context"
"encoding/json"
)
type Result struct {
Name string
Output Output
Err error
}
// Iterator represents a iterable object that is capable of returning its
// values one at a time, permitting it to be iterated over in a for-loop.
type Iterator struct {
ch chan Result
breakCh chan struct{}
}
func NewIterator(ctx context.Context, f func(sender *IteratorSender)) *Iterator {
ch := make(chan Result)
breakCh := make(chan struct{}, 1)
sender := &IteratorSender{ctx: ctx, ch: ch, breakCh: breakCh}
go f(sender)
return &Iterator{
ch: ch,
breakCh: breakCh,
}
}
func (i *Iterator) Next() <-chan Result {
return i.ch
}
func (i *Iterator) Break() {
i.breakCh <- struct{}{}
}
func (i *Iterator) String() string {
return "<Iterator>"
}
func (i *Iterator) MarshalJSON() ([]byte, error) {
return json.Marshal(i.String())
}
// Equal implements the custom equality method of github.com/google/go-cmp.
func (i *Iterator) Equal(o *Iterator) bool {
return i.String() == o.String()
}
// IteratorSender is a helper for sending data to an iterator.
type IteratorSender struct {
ctx context.Context
ch chan<- Result
breakCh <-chan struct{}
}
// Send sends data to the internal channel. If the internal context is done
// (cancelled or timed out), it will mark the continue flag (whether to continue
// sending) as false.
func (s *IteratorSender) Send(output Output, err error) (continue_ bool) {
select {
case s.ch <- Result{Output: output, Err: err}:
return true
case <-s.ctx.Done():
return false
case <-s.breakCh:
return false
}
}
// End ends the iteration by closing the internal channel.
func (s *IteratorSender) End() {
close(s.ch)
}