mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-23 19:42:09 +00:00
types/logid: add Add method (#12478)
The Add method derives a new ID by adding a signed integer to the ID, treating it as an unsigned 256-bit big-endian integer. We also add Less and Compare methods to PrivateID to provide feature parity with existing methods on PublicID. Updates tailscale/corp#11038 Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"slices"
|
||||
"unicode/utf8"
|
||||
)
|
||||
@@ -38,6 +39,12 @@ func ParsePrivateID(in string) (out PrivateID, err error) {
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Add adds i to the id, treating it as an unsigned 256-bit big-endian integer,
|
||||
// and returns the resulting ID.
|
||||
func (id PrivateID) Add(i int64) PrivateID {
|
||||
return add(id, i)
|
||||
}
|
||||
|
||||
func (id PrivateID) AppendText(b []byte) ([]byte, error) {
|
||||
return hex.AppendEncode(b, id[:]), nil
|
||||
}
|
||||
@@ -54,6 +61,14 @@ func (id PrivateID) String() string {
|
||||
return string(hex.AppendEncode(nil, id[:]))
|
||||
}
|
||||
|
||||
func (id1 PrivateID) Less(id2 PrivateID) bool {
|
||||
return id1.Compare(id2) < 0
|
||||
}
|
||||
|
||||
func (id1 PrivateID) Compare(id2 PrivateID) int {
|
||||
return slices.Compare(id1[:], id2[:])
|
||||
}
|
||||
|
||||
func (id PrivateID) IsZero() bool {
|
||||
return id == PrivateID{}
|
||||
}
|
||||
@@ -74,6 +89,12 @@ func ParsePublicID(in string) (out PublicID, err error) {
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Add adds i to the id, treating it as an unsigned 256-bit big-endian integer,
|
||||
// and returns the resulting ID.
|
||||
func (id PublicID) Add(i int64) PublicID {
|
||||
return add(id, i)
|
||||
}
|
||||
|
||||
func (id PublicID) AppendText(b []byte) ([]byte, error) {
|
||||
return hex.AppendEncode(b, id[:]), nil
|
||||
}
|
||||
@@ -118,3 +139,22 @@ func parseID[Bytes []byte | string](funcName string, out *[32]byte, in Bytes) (e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func add(id [32]byte, i int64) [32]byte {
|
||||
var out uint64
|
||||
switch {
|
||||
case i < 0:
|
||||
borrow := ^uint64(i) + 1 // twos-complement inversion
|
||||
for i := 0; i < 4 && borrow > 0; i++ {
|
||||
out, borrow = bits.Sub64(binary.BigEndian.Uint64(id[8*(3-i):]), borrow, 0)
|
||||
binary.BigEndian.PutUint64(id[8*(3-i):], out)
|
||||
}
|
||||
case i > 0:
|
||||
carry := uint64(i)
|
||||
for i := 0; i < 4 && carry > 0; i++ {
|
||||
out, carry = bits.Add64(binary.BigEndian.Uint64(id[8*(3-i):]), carry, 0)
|
||||
binary.BigEndian.PutUint64(id[8*(3-i):], out)
|
||||
}
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
Reference in New Issue
Block a user