-
Notifications
You must be signed in to change notification settings - Fork 0
/
varint.go
105 lines (91 loc) · 2.28 KB
/
varint.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Decode a variable integer from the given data buffer.
// Returns the uint64 bit value and a data slice positioned
// after the variable integer
package primitives
import (
"math"
"github.com/DCNT-developer/dcnt/common/primitives/random"
)
func RandomVarInt() uint64 {
length := random.RandIntBetween(1, 10)
switch length {
case 1:
return random.RandUInt64Between(0x00, 0x7F)
case 2:
return random.RandUInt64Between(0x80, 0x3FFF)
case 3:
return random.RandUInt64Between(0x4000, 0x1FFFFF)
case 4:
return random.RandUInt64Between(0x200000, 0x0FFFFFFF)
case 5:
return random.RandUInt64Between(0x10000000, 0x7FFFFFFFF)
case 6:
return random.RandUInt64Between(0x800000000, 0x3FFFFFFFFFF)
case 7:
return random.RandUInt64Between(0x40000000000, 0x1FFFFFFFFFFFF)
case 8:
return random.RandUInt64Between(0x2000000000000, 0x0FFFFFFFFFFFFFF)
case 9:
return random.RandUInt64Between(0x100000000000000, 0x7FFFFFFFFFFFFFFF)
case 10:
return random.RandUInt64Between(0x8000000000000000, math.MaxUint64)
default:
panic("Internal varint error")
}
return 0
}
func VarIntLength(v uint64) uint64 {
buf := new(Buffer)
EncodeVarInt(buf, v)
return uint64(buf.Len())
}
func DecodeVarInt(data []byte) (uint64, []byte) {
return DecodeVarIntGo(data)
}
func EncodeVarInt(out *Buffer, v uint64) error {
return EncodeVarIntGo(out, v)
}
// Decode a variable integer from the given data buffer.
// We use the algorithm used by Go, only BigEndian.
func DecodeVarIntGo(data []byte) (uint64, []byte) {
if data == nil || len(data) < 1 {
return 0, data
}
var v uint64
var cnt int
var b byte
for cnt, b = range data {
v = v << 7
v += uint64(b) & 0x7F
if b < 0x80 {
break
}
}
return v, data[cnt+1:]
}
// Encode an integer as a variable int into the given data buffer.
func EncodeVarIntGo(out *Buffer, v uint64) error {
if v == 0 {
out.WriteByte(0)
}
h := v
start := false
if 0x8000000000000000&h != 0 { // Deal with the high bit set; Zero
out.WriteByte(0x81) // doesn't need this, only when set.
start = true // Going the whole 10 byte path!
}
for i := 0; i < 9; i++ {
b := byte(h >> 56) // Get the top 7 bits
if b != 0 || start {
start = true
if i != 8 {
b = b | 0x80
} else {
b = b & 0x7F
}
out.WriteByte(b)
}
h = h << 7
}
return nil
}