-
Notifications
You must be signed in to change notification settings - Fork 258
/
counter.go
87 lines (75 loc) · 2.41 KB
/
counter.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
package shares
import (
"github.com/celestiaorg/celestia-app/pkg/appconsts"
)
type CompactShareCounter struct {
lastShares int
lastRemainder int
shares int
// remainder is the number of bytes used for data in the last share
remainder int
}
// NewCompactShareCounter creates a new instance of a counter which calculates the amount
// of compact shares a set of data will be split into.
func NewCompactShareCounter() *CompactShareCounter {
return &CompactShareCounter{}
}
// Add adds the length of the data to the counter and returns the amount of shares
// the counter has been increased by.
func (c *CompactShareCounter) Add(dataLen int) int {
// Increment the data len by the varint that will prefix the data.
dataLen += DelimLen(uint64(dataLen))
// save a copy of the previous state
c.lastRemainder = c.remainder
c.lastShares = c.shares
// if this is the first share, calculate how much is taken up by dataLen
if c.shares == 0 {
if dataLen >= appconsts.FirstCompactShareContentSize-c.remainder {
dataLen -= (appconsts.FirstCompactShareContentSize - c.remainder)
c.shares++
c.remainder = 0
} else {
c.remainder += dataLen
dataLen = 0
}
}
// next, look to fill the remainder of the continuation share
if dataLen >= (appconsts.ContinuationCompactShareContentSize - c.remainder) {
dataLen -= (appconsts.ContinuationCompactShareContentSize - c.remainder)
c.shares++
c.remainder = 0
} else {
c.remainder += dataLen
dataLen = 0
}
// finally, divide the remaining dataLen into the continuation shares and update
// the remainder
if dataLen > 0 {
c.shares += dataLen / appconsts.ContinuationCompactShareContentSize
c.remainder = dataLen % appconsts.ContinuationCompactShareContentSize
}
// calculate the diff between before and after
diff := c.shares - c.lastShares
if c.lastRemainder == 0 && c.remainder > 0 {
diff++
} else if c.lastRemainder > 0 && c.remainder == 0 {
diff--
}
return diff
}
// Revert reverts the last Add operation. This can be called multiple times but only works
// the first time after an add operation.
func (c *CompactShareCounter) Revert() {
c.shares = c.lastShares
c.remainder = c.lastRemainder
}
// Size returns the amount of shares the compact share counter has counted.
func (c *CompactShareCounter) Size() int {
if c.remainder == 0 {
return c.shares
}
return c.shares + 1
}
func (c *CompactShareCounter) Remainder() int {
return c.remainder
}