pw_varint: MaxValueInBytes function
This adds a function to the varint API that returns the maximum value
that can be encoded into a given number of bytes.
Change-Id: I6be36117623e3cb9ec90fc4c5eb88b42196385aa
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/39581
Commit-Queue: Alexei Frolov <frolv@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_varint/docs.rst b/pw_varint/docs.rst
index 3327ccd..58c90f9 100644
--- a/pw_varint/docs.rst
+++ b/pw_varint/docs.rst
@@ -28,6 +28,11 @@
Returns the size of a signed integer when ZigZag encoded as a varint.
+.. cpp:function:: uint64_t MaxValueInBytes(size_t bytes)
+
+Returns the maximum integer value that can be encoded as a varint into the
+specified number of bytes.
+
Dependencies
============
* ``pw_span``
diff --git a/pw_varint/public/pw_varint/varint.h b/pw_varint/public/pw_varint/varint.h
index 4432e19..9d0e0ce 100644
--- a/pw_varint/public/pw_varint/varint.h
+++ b/pw_varint/public/pw_varint/varint.h
@@ -198,6 +198,29 @@
return EncodedSize(ZigZagEncode(integer));
}
+// Returns the maximum integer value that can be encoded in a varint of the
+// specified number of bytes.
+//
+// These values are also listed in the table below. Zigzag encoding cuts these
+// in half, as positive and negative integers are alternated.
+//
+// Bytes Max value
+// 1 127
+// 2 16,383
+// 3 2,097,151
+// 4 268,435,455
+// 5 34,359,738,367 -- needed for max uint32 value
+// 6 4,398,046,511,103
+// 7 562,949,953,421,311
+// 8 72,057,594,037,927,935
+// 9 9,223,372,036,854,775,807
+// 10 uint64 max value
+//
+constexpr uint64_t MaxValueInBytes(size_t bytes) {
+ return bytes >= kMaxVarint64SizeBytes ? std::numeric_limits<uint64_t>::max()
+ : (uint64_t(1) << (7 * bytes)) - 1;
+}
+
} // namespace varint
} // namespace pw
diff --git a/pw_varint/varint_test.cc b/pw_varint/varint_test.cc
index 2d373d2..27282c4 100644
--- a/pw_varint/varint_test.cc
+++ b/pw_varint/varint_test.cc
@@ -1054,5 +1054,29 @@
EXPECT_EQ(ZigZagEncodedSize(std::numeric_limits<int64_t>::max()), 10u);
}
+constexpr uint64_t CalculateMaxValueInBytes(size_t bytes) {
+ uint64_t value = 0;
+ for (size_t i = 0; i < bytes; ++i) {
+ value |= uint64_t(0x7f) << (7 * i);
+ }
+ return value;
+}
+
+TEST(Varint, MaxValueInBytes) {
+ static_assert(MaxValueInBytes(0) == 0);
+ static_assert(MaxValueInBytes(1) == 0x7f);
+ static_assert(MaxValueInBytes(2) == 0x3fff);
+ static_assert(MaxValueInBytes(3) == 0x1fffff);
+ static_assert(MaxValueInBytes(4) == 0x0fffffff);
+ static_assert(MaxValueInBytes(5) == CalculateMaxValueInBytes(5));
+ static_assert(MaxValueInBytes(6) == CalculateMaxValueInBytes(6));
+ static_assert(MaxValueInBytes(7) == CalculateMaxValueInBytes(7));
+ static_assert(MaxValueInBytes(8) == CalculateMaxValueInBytes(8));
+ static_assert(MaxValueInBytes(9) == CalculateMaxValueInBytes(9));
+ static_assert(MaxValueInBytes(10) == std::numeric_limits<uint64_t>::max());
+ static_assert(MaxValueInBytes(11) == std::numeric_limits<uint64_t>::max());
+ static_assert(MaxValueInBytes(100) == std::numeric_limits<uint64_t>::max());
+}
+
} // namespace
} // namespace pw::varint