-
Notifications
You must be signed in to change notification settings - Fork 4
/
bit_setter.go
98 lines (87 loc) · 3.09 KB
/
bit_setter.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
package uuid
// getBit returns the value of a bit at a specified positon in UUID
func (b uuidBase) getBit(index int) bool {
pos := index / 8
j := uint(index % 8)
j = 7 - j
return (b[pos] & (uint8(1) << j)) != 0
}
// getBit returns the value of a bit at a specified positon in UUIDv7
func (b UUIDv7) getBit(index int) bool {
return uuidBase(b).getBit(index)
}
// getBit returns the value of a bit at a specified positon in given byte array
func getBit(b []byte, index int) bool {
pos := index / 8
j := uint(index % 8)
j = 7 - j
return (b[pos] & (uint8(1) << j)) != 0
}
// setBit sets the value of a bit at a specified positon in []byte
func setBit(b []byte, index int, value bool) {
pos := index / 8
j := uint(index % 8)
j = 7 - j
if value {
b[pos] |= (uint8(1) << j)
} else {
b[pos] &= ^(uint8(1) << j)
}
}
// setBit sets the value of a bit at a specified positon in UUID
func (b uuidBase) setBit(index int, value bool) uuidBase {
pos := index / 8
j := uint(index % 8)
j = 7 - j
if value {
b[pos] |= (uint8(1) << j)
} else {
b[pos] &= ^(uint8(1) << j)
}
return b
}
// setBit sets the value of a bit at a specified positon in UUIDv7
func (b UUIDv7) setBit(index int, value bool) UUIDv7 {
return UUIDv7(uuidBase(b).setBit(index, value))
}
// indexer returns updated index of a bit in the array of bits. It skips bits 48-51 and 64,65
// for those containt information about Version and Variant and can't be populated by the
// precision bits. It also omits first 36 bits of timestamp at the beginning of the GUID
func indexer(input int) int {
out := 35 + input //Skip the TS block and start counting right after ts block
if input > 11 { //If we are bumbing into a ver block, skip it
out += 4
}
if input > 23 { //If we are bumping into a var block
out += 2
}
return out
}
// absoluteIndexer returns updated index of a bit in the array of bits. It skips bits 48-51 and 64,65
// for those containt information about Version and Variant and can't be populated by the
// precision bits. It DOES NOT omit first 36 bits of timestamp at the beginning of the GUID
func absoluteIndexer(input int) int {
out := input //Skip the TS block and start counting right after ts block
if input > 35+11 { //If we are bumbing into a ver block, skip it
out += 4
}
if input > 35+23 { //If we are bumping into a var block
out += 2
}
return out
}
// stack adds a chunk of bits, encoded as []byte at the selected started position, with respect to the timestamp, version and variant values.
func (b UUIDv7) stack(startingPosition int, value []byte, length int) (UUIDv7, int) {
rettype, retval := (uuidBase(b)).stack(startingPosition, value, length)
return UUIDv7(rettype), retval
}
// stack adds a chunk of bits, encoded as []byte at the selected started position, with respect to the timestamp, version and variant values.
func (b uuidBase) stack(startingPosition int, value []byte, length int) (uuidBase, int) {
cnt := 0
for i := startingPosition; i < startingPosition+length; i++ {
bit := getBit(value, (len(value)*8-1)-cnt)
b = b.setBit(absoluteIndexer(i), bit)
cnt++
}
return b, startingPosition + length
}