/
uint64.go
121 lines (100 loc) · 2.94 KB
/
uint64.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package j57
import "github.com/foxcapades/tally-go/v1/tally"
// ╔════════════════════════════════════════════════════════════════════════╗ //
// ║ ║ //
// ║ Uint64 Serialization ║ //
// ║ ║ //
// ╚════════════════════════════════════════════════════════════════════════╝
// SerializeUint64 converts the given uint64 value to a base57 encoded byte
// slice.
//
// The byte slice returned may be 1-12 bytes in length.
func SerializeUint64(v uint64) []byte {
if v == 0 {
return []byte{min}
}
sz := SizeUint64(v)
pos := sz
out := make([]byte, pos)
for v > 0 {
pos--
out[pos] = byte(v%Base) + min
v /= Base
}
out[0] = uint8(sz-1) + min
return out
}
// AppendUint64 converts the given uint64 value to base57 and writes it
// to the given buffer starting at off.Cur().
//
// The given offset value will be incremented as the buffer is written and after
// this function call will be at the next writable offset position.
//
// WARNING: This method makes no attempt to verify that the given byte buffer is
// actually long enough to hold the serialized value. The buffer size should be
// at least SizeUint64(v) in length.
func AppendUint64(v uint64, buf []byte, off *tally.UTally) (wrote int) {
if v == 0 {
buf[off.Inc()] = min
wrote = 1
return
}
sz := SizeUint64(v)
pos := sz + off.Cur()
wrote = int(sz)
cur := off.Add(sz)
for v > 0 {
pos--
buf[pos] = byte(v%Base) + min
v /= Base
}
buf[cur] = byte(sz-1) + min
return
}
func DeserializeUint64(v []byte, off *tally.UTally) (out uint64, err error) {
sz := int(DeserializeUDigit(v[off.Inc()]))
if sz < 0 {
return 0, NewJASCByteError(0)
} else if sz == 0 {
return 0, nil
}
i := sz + int(off.Add(uint(sz)))
for j := 0; j < sz; j++ {
i--
out += uint64(DeserializeUDigit(v[i])) * powU64(j)
}
return out, nil
}
// SizeUint64 returns the number of bytes needed in a byte buffer to hold the
// serialized form of the given uint64 value.
//
// This size includes the byte needed for the number size header.
func SizeUint64(v uint64) uint {
switch true {
case v >= 362_033_331_456_891_249:
return 12
case v >= 6_351_461_955_384_057:
return 11
case v >= 111_429_157_112_001:
return 10
case v >= 1_954_897_493_193:
return 9
case v >= 34_296_447_249:
return 8
case v >= 601_692_057:
return 7
default:
return SizeUint32(uint32(v))
}
}
func powU64(a int) (out uint64) {
if a == 0 {
return 1
}
tmp := uint64(Base)
out = 1
for i := 0; i < a; i++ {
out *= tmp
}
return
}