Skip to content

Commit

Permalink
types: Fix encoding of negative varint
Browse files Browse the repository at this point in the history
We would sometimes produce an unnecessary extra 0xff prefix byte.

The new encoding matches what cassandra does.

This was both a efficiency and correctness issue, as using varint in a
key could produce different tokens.

Fixes scylladb#5656

Signed-off-by: Rafael Ávila de Espíndola <espindola@scylladb.com>
(cherry picked from commit c89c90d)
  • Loading branch information
espindola authored and avikivity committed Feb 2, 2020
1 parent 44bc617 commit 71d8efa
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 2 deletions.
2 changes: 2 additions & 0 deletions tests/types_test.cc
Expand Up @@ -370,6 +370,8 @@ BOOST_AUTO_TEST_CASE(test_varint) {
BOOST_CHECK_EQUAL(value_cast<boost::multiprecision::cpp_int>(varint_type->deserialize(from_hex("00deadbeef"))), boost::multiprecision::cpp_int("0xdeadbeef"));
BOOST_CHECK_EQUAL(value_cast<boost::multiprecision::cpp_int>(varint_type->deserialize(from_hex("00ffffffffffffffffffffffffffffffff"))), boost::multiprecision::cpp_int("340282366920938463463374607431768211455"));

BOOST_REQUIRE_EQUAL(from_hex("80000000"), varint_type->decompose(boost::multiprecision::cpp_int(-2147483648)));

test_parsing_fails(varint_type, "1A");
}

Expand Down
13 changes: 11 additions & 2 deletions types.cc
Expand Up @@ -1470,6 +1470,13 @@ class varint_type_impl : public concrete_type<boost::multiprecision::cpp_int> {
}
out = std::copy(b.crbegin(), b.crend(), out);
}
static size_t serialized_size_aux(const boost::multiprecision::cpp_int& num) {
if (num) {
return align_up(boost::multiprecision::msb(num) + 2, 8u) / 8;
} else {
return 1;
}
}
virtual size_t serialized_size(const void* value) const override {
if (!value) {
return 0;
Expand All @@ -1482,8 +1489,10 @@ class varint_type_impl : public concrete_type<boost::multiprecision::cpp_int> {
if (!num) {
return 1;
}
auto pnum = abs(num);
return align_up(boost::multiprecision::msb(pnum) + 2, 8u) / 8;
if (num < 0) {
return serialized_size_aux(-num - 1);
}
return serialized_size_aux(num);
}
virtual int32_t compare(bytes_view v1, bytes_view v2) const override {
if (v1.empty()) {
Expand Down

0 comments on commit 71d8efa

Please sign in to comment.