mirror of
https://github.com/muun/recovery.git
synced 2025-02-23 11:32:33 -05:00
82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
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)
|
|
}
|
|
}
|