-
Notifications
You must be signed in to change notification settings - Fork 127
/
replay_set.go
81 lines (69 loc) · 1.95 KB
/
replay_set.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
package sphinx
import (
"encoding/binary"
"io"
)
// ReplaySet is a data structure used to efficiently record the occurrence of
// replays, identified by sequence number, when processing a Batch. Its primary
// functionality includes set construction, membership queries, and merging of
// replay sets.
type ReplaySet struct {
replays map[uint16]struct{}
}
// NewReplaySet initializes an empty replay set.
func NewReplaySet() *ReplaySet {
return &ReplaySet{
replays: make(map[uint16]struct{}),
}
}
// Size returns the number of elements in the replay set.
func (rs *ReplaySet) Size() int {
return len(rs.replays)
}
// Add inserts the provided index into the replay set.
func (rs *ReplaySet) Add(idx uint16) {
rs.replays[idx] = struct{}{}
}
// Contains queries the contents of the replay set for membership of a
// particular index.
func (rs *ReplaySet) Contains(idx uint16) bool {
_, ok := rs.replays[idx]
return ok
}
// Merge adds the contents of the provided replay set to the receiver's set.
func (rs *ReplaySet) Merge(rs2 *ReplaySet) {
for seqNum := range rs2.replays {
rs.Add(seqNum)
}
}
// Encode serializes the replay set into an io.Writer suitable for storage. The
// replay set can be recovered using Decode.
func (rs *ReplaySet) Encode(w io.Writer) error {
for seqNum := range rs.replays {
err := binary.Write(w, binary.BigEndian, seqNum)
if err != nil {
return err
}
}
return nil
}
// Decode reconstructs a replay set given a io.Reader. The byte
// slice is assumed to be even in length, otherwise resulting in failure.
func (rs *ReplaySet) Decode(r io.Reader) error {
for {
// seqNum provides to buffer to read the next uint16 index.
var seqNum uint16
err := binary.Read(r, binary.BigEndian, &seqNum)
switch err {
case nil:
// Successful read, proceed.
case io.EOF:
return nil
default:
// Can return ErrShortBuffer or ErrUnexpectedEOF.
return err
}
// Add this decoded sequence number to the set.
rs.Add(seqNum)
}
}