-
Notifications
You must be signed in to change notification settings - Fork 0
/
bit.go
88 lines (75 loc) · 2.12 KB
/
bit.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
package consentstring
import (
"fmt"
"time"
)
// custom error types
var (
ErrISO639 = fmt.Errorf("language was not entered in two-letter ISO639-1")
ErrPurposeList = fmt.Errorf("incorrect purposes array size")
)
// bit is a convience type to abstract []byte
type bit []byte
// setBit sets a single byte at a specified position
func (b bit) setBit(index int) {
byteIndex := index / 8
shift := uint((byteIndex+1)*8 - index - 1)
b[byteIndex] |= byte(1 << shift)
}
// unsetBit unsets a single byte at a specified position
func (b bit) unsetBit(index int) {
byteIndex := index / 8
shift := uint((byteIndex+1)*8 - index - 1)
b[byteIndex] &= ^(1 << shift)
}
func (b bit) setPurposes(purposes []uint) error {
if len(purposes) != 5 {
return ErrPurposeList
}
for i, p := range purposes {
if p == 1 {
b.setBit(purposesOffset + i)
} else {
b.unsetBit(purposesOffset + i)
}
}
return nil
}
// setInt sets an interger with specified padding
func (b bit) setInt(startInclusive int, size int, to int) {
b.setNumber(startInclusive, size, to)
}
// setDateToDeciseconds converts time.Time to deciseconds and sets it's bit values
func (b bit) setDateToDeciseconds(startInclusive int, size int, t time.Time) {
deciseconds := int64(t.UnixNano() / 1e8)
b.setNumberInt64(startInclusive, size, deciseconds)
}
// setSixBitString converts the a two-letter ISO639-1 language code to it's bit values
func (b bit) setSixBitString(startInclusive int, size int, lang string) error {
if len(lang) != 2 {
return ErrISO639
}
for i, r := range lang {
charCode := int(r) - 65
b.setInt(startInclusive+(i*6), 6, charCode)
}
return nil
}
func (b bit) setNumberInt64(startInclusive int, size int, to int64) {
for i := size - 1; i >= 0; i-- {
index := startInclusive + i
byteIndex := index / 8
shift := uint((byteIndex+1)*8 - index - 1)
b[byteIndex] |= byte((to % 2) << shift)
to /= 2
}
}
func (b bit) setNumber(startInclusive int, size int, to int) {
for i := size - 1; i >= 0; i-- {
index := startInclusive + i
byteIndex := index / 8
shift := uint((byteIndex+1)*8 - index - 1)
b[byteIndex] |= byte((to % 2) << shift)
to /= 2
}
}