-
Notifications
You must be signed in to change notification settings - Fork 0
/
seeder.go
90 lines (78 loc) · 2.24 KB
/
seeder.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
package lizt
import (
"fmt"
"sync/atomic"
)
// SeedingIterator is an iterator that reads from a slice.
type SeedingIterator struct {
Seeder
PointerIterator
seedIter PointerIterator
totalPlanted *atomic.Int64
plantEvery int
}
type SeedingIteratorConfig struct {
PointerIter PointerIterator
SeedIter PointerIterator
PlantEvery int
}
// NewSeedingIterator returns a new slice iterator.
func NewSeedingIterator(cfg SeedingIteratorConfig) *SeedingIterator {
return &SeedingIterator{
PointerIterator: cfg.PointerIter,
seedIter: cfg.SeedIter,
plantEvery: cfg.PlantEvery,
totalPlanted: new(atomic.Int64),
}
}
// Planted returns how many seedIter have been planted.
func (si *SeedingIterator) Planted() int64 {
return si.totalPlanted.Load()
}
// PlantEvery returns how often the seedIter are planted.
func (si *SeedingIterator) PlantEvery() int {
return si.plantEvery
}
// inc increments the total planted counter.
func (si *SeedingIterator) inc() {
si.totalPlanted.Add(1)
}
// Next returns the next line from the iterator and will automatically seed every PlantEvery() lines.
func (si *SeedingIterator) Next(count int) ([]string, error) {
lines, _, err := si.nextSeed(count)
if err != nil {
return nil, err
}
return lines, nil
}
// NextSeed returns the next line from the iterator and will automatically seed every PlantEvery() lines.
// The difference from the interface Next() is that this returns a bool indicating if a seed was planted.
func (si *SeedingIterator) NextSeed(count int) ([]string, bool, error) {
return si.nextSeed(count)
}
func (si *SeedingIterator) nextSeed(count int) ([]string, bool, error) {
var lines []string
seeded := false
for i := 0; i < count; i++ {
sent := si.Pointer() + uint64(si.Planted())
if sent%uint64(si.PlantEvery()) == 0 {
seed, err := si.seedIter.Next(1)
if err != nil {
return nil, seeded, fmt.Errorf("seed iter next: %w", err)
}
seeded = true
si.inc()
lines = append(lines, seed[0])
} else {
next, err := si.PointerIterator.Next(1)
if err != nil {
if len(lines) == 0 {
return nil, seeded, fmt.Errorf("file: %s -> %w", si.Name(), err)
}
return lines, seeded, nil
}
lines = append(lines, next[0])
}
}
return lines, seeded, nil
}