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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
package ksuid
import "fmt"
// uint128 represents an unsigned 128 bits little endian integer.
type uint128 [2]uint64
func uint128Payload(ksuid KSUID) uint128 {
return makeUint128FromPayload(ksuid[timestampLengthInBytes:])
}
func makeUint128(high uint64, low uint64) uint128 {
return uint128{low, high}
}
func makeUint128FromPayload(payload []byte) uint128 {
return uint128{
// low
uint64(payload[8])<<56 |
uint64(payload[9])<<48 |
uint64(payload[10])<<40 |
uint64(payload[11])<<32 |
uint64(payload[12])<<24 |
uint64(payload[13])<<16 |
uint64(payload[14])<<8 |
uint64(payload[15]),
// high
uint64(payload[0])<<56 |
uint64(payload[1])<<48 |
uint64(payload[2])<<40 |
uint64(payload[3])<<32 |
uint64(payload[4])<<24 |
uint64(payload[5])<<16 |
uint64(payload[6])<<8 |
uint64(payload[7]),
}
}
func (v uint128) ksuid(timestamp uint32) KSUID {
return KSUID{
// time
byte(timestamp >> 24),
byte(timestamp >> 16),
byte(timestamp >> 8),
byte(timestamp),
// high
byte(v[1] >> 56),
byte(v[1] >> 48),
byte(v[1] >> 40),
byte(v[1] >> 32),
byte(v[1] >> 24),
byte(v[1] >> 16),
byte(v[1] >> 8),
byte(v[1]),
// low
byte(v[0] >> 56),
byte(v[0] >> 48),
byte(v[0] >> 40),
byte(v[0] >> 32),
byte(v[0] >> 24),
byte(v[0] >> 16),
byte(v[0] >> 8),
byte(v[0]),
}
}
func (v uint128) bytes() [16]byte {
return [16]byte{
// high
byte(v[1] >> 56),
byte(v[1] >> 48),
byte(v[1] >> 40),
byte(v[1] >> 32),
byte(v[1] >> 24),
byte(v[1] >> 16),
byte(v[1] >> 8),
byte(v[1]),
// low
byte(v[0] >> 56),
byte(v[0] >> 48),
byte(v[0] >> 40),
byte(v[0] >> 32),
byte(v[0] >> 24),
byte(v[0] >> 16),
byte(v[0] >> 8),
byte(v[0]),
}
}
func (v uint128) String() string {
return fmt.Sprintf("0x%016X%016X", v[0], v[1])
}
const wordBitSize = 64
func cmp128(x, y uint128) int {
if x[1] < y[1] {
return -1
}
if x[1] > y[1] {
return 1
}
if x[0] < y[0] {
return -1
}
if x[0] > y[0] {
return 1
}
return 0
}
func add128(x, y uint128) (z uint128) {
x0 := x[0]
y0 := y[0]
z0 := x0 + y0
z[0] = z0
c := (x0&y0 | (x0|y0)&^z0) >> (wordBitSize - 1)
z[1] = x[1] + y[1] + c
return
}
func sub128(x, y uint128) (z uint128) {
x0 := x[0]
y0 := y[0]
z0 := x0 - y0
z[0] = z0
c := (y0&^x0 | (y0|^x0)&z0) >> (wordBitSize - 1)
z[1] = x[1] - y[1] - c
return
}
func incr128(x uint128) uint128 {
return add128(x, uint128{1, 0})
}
|