diff --git a/lib/encoding/int.go b/lib/encoding/int.go index 445345aeb..2d9a359c4 100644 --- a/lib/encoding/int.go +++ b/lib/encoding/int.go @@ -165,16 +165,19 @@ func marshalVarInt64sSlow(dst []byte, vs []int64) []byte { return dst } -// UnmarshalVarInt64 returns unmarshaled int64 from src and returns -// the remaining tail from src. +// UnmarshalVarInt64 returns unmarshaled int64 from src and returns the remaining tail from src. func UnmarshalVarInt64(src []byte) ([]byte, int64, error) { - var tmp [1]int64 - tail, err := UnmarshalVarInt64s(tmp[:], src) - return tail, tmp[0], err + // TODO substitute binary.Uvarint with binary.Varint when benchmark results will show it is faster. + // It is slower on amd64/linux Go1.22. + u64, offset := binary.Uvarint(src) + if offset <= 0 { + return src, 0, fmt.Errorf("cannot unmarshal varint") + } + i64 := int64(int64(u64>>1) ^ (int64(u64<<63) >> 63)) + return src[offset:], i64, nil } -// UnmarshalVarInt64s unmarshals len(dst) int64 values from src to dst -// and returns the remaining tail from src. +// UnmarshalVarInt64s unmarshals len(dst) int64 values from src to dst and returns the remaining tail from src. func UnmarshalVarInt64s(dst []int64, src []byte) ([]byte, error) { if len(src) < len(dst) { return src, fmt.Errorf("too small len(src)=%d; it must be bigger or equal to len(dst)=%d", len(src), len(dst)) @@ -358,18 +361,16 @@ func marshalVarUint64sSlow(dst []byte, us []uint64) []byte { return dst } -// UnmarshalVarUint64 returns unmarshaled uint64 from src and returns -// the remaining tail from src. +// UnmarshalVarUint64 returns unmarshaled uint64 from src and returns the remaining tail from src. func UnmarshalVarUint64(src []byte) ([]byte, uint64, error) { u64, offset := binary.Uvarint(src) if offset <= 0 { - return src, 0, fmt.Errorf("cannot read varuint64") + return src, 0, fmt.Errorf("cannot read varuint") } return src[offset:], u64, nil } -// UnmarshalVarUint64s unmarshals len(dst) uint64 values from src to dst -// and returns the remaining tail from src. +// UnmarshalVarUint64s unmarshals len(dst) uint64 values from src to dst and returns the remaining tail from src. func UnmarshalVarUint64s(dst []uint64, src []byte) ([]byte, error) { if len(src) < len(dst) { return src, fmt.Errorf("too small len(src)=%d; it must be bigger or equal to len(dst)=%d", len(src), len(dst))