-
-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathuint128.go
137 lines (118 loc) · 3.66 KB
/
uint128.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2023 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2017 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
package utils
import (
"encoding/binary"
"encoding/hex"
"github.com/cockroachdb/errors"
)
// Uint128 is a big-endian 128 bit unsigned integer which wraps two uint64s.
type Uint128 struct {
Hi, Lo uint64
}
// GetBytes returns a big-endian byte representation.
func (u Uint128) GetBytes() []byte {
buf := make([]byte, 16)
binary.BigEndian.PutUint64(buf[:8], u.Hi)
binary.BigEndian.PutUint64(buf[8:], u.Lo)
return buf
}
// String returns a hexadecimal string representation.
func (u Uint128) String() string {
return hex.EncodeToString(u.GetBytes())
}
// Equal returns whether or not the Uint128 are equivalent.
func (u Uint128) Equal(o Uint128) bool {
return u.Hi == o.Hi && u.Lo == o.Lo
}
// Compare compares the two Uint128.
func (u Uint128) Compare(o Uint128) int {
if u.Hi > o.Hi {
return 1
} else if u.Hi < o.Hi {
return -1
} else if u.Lo > o.Lo {
return 1
} else if u.Lo < o.Lo {
return -1
}
return 0
}
// Add returns a new Uint128 incremented by n.
func (u Uint128) Add(n uint64) Uint128 {
lo := u.Lo + n
hi := u.Hi
if u.Lo > lo {
hi++
}
return Uint128{hi, lo}
}
// Sub returns a new Uint128 decremented by n.
func (u Uint128) Sub(n uint64) Uint128 {
lo := u.Lo - n
hi := u.Hi
if u.Lo < lo {
hi--
}
return Uint128{hi, lo}
}
// And returns a new Uint128 that is the bitwise AND of two Uint128 values.
func (u Uint128) And(o Uint128) Uint128 {
return Uint128{u.Hi & o.Hi, u.Lo & o.Lo}
}
// Or returns a new Uint128 that is the bitwise OR of two Uint128 values.
func (u Uint128) Or(o Uint128) Uint128 {
return Uint128{u.Hi | o.Hi, u.Lo | o.Lo}
}
// Xor returns a new Uint128 that is the bitwise XOR of two Uint128 values.
func (u Uint128) Xor(o Uint128) Uint128 {
return Uint128{u.Hi ^ o.Hi, u.Lo ^ o.Lo}
}
// FromBytes parses the byte slice as a 128 bit big-endian unsigned integer.
// The caller is responsible for ensuring the byte slice contains 16 bytes.
func FromBytes(b []byte) Uint128 {
hi := binary.BigEndian.Uint64(b[:8])
lo := binary.BigEndian.Uint64(b[8:])
return Uint128{hi, lo}
}
// FromString parses a hexadecimal string as a 128-bit big-endian unsigned integer.
func FromString(s string) (Uint128, error) {
if len(s) > 32 {
return Uint128{}, errors.Errorf("input string %s too large for uint128", s)
}
bytes, err := hex.DecodeString(s)
if err != nil {
return Uint128{}, errors.Wrapf(err, "could not decode %s as hex", s)
}
// Grow the byte slice if it's smaller than 16 bytes, by prepending 0s
if len(bytes) < 16 {
bytesCopy := make([]byte, 16)
copy(bytesCopy[(16-len(bytes)):], bytes)
bytes = bytesCopy
}
return FromBytes(bytes), nil
}
// FromInts takes in two unsigned 64-bit integers and constructs a Uint128.
func FromInts(hi uint64, lo uint64) Uint128 {
return Uint128{hi, lo}
}