pw_protobuf: Adds serialized size of field keys

Adds size_t pw::protobuf::SizeOfFieldKey(uint32_t field_number) to
help better estimate the serialized size cost for specific fields
which can be much smaller than kMaxSizeOfFieldKey.

Note that the API does not ask for the wiretype which is in the
actual field key (AKA tag) as it does not impact the serialized
size and only makes the API more verbose.

To enable this, pw::varint::{EncodedSize,ZigZagEncodedSize} were
changed to be constexpr, where the C functions invoke C++ instead.

Change-Id: Icbe4250e7acc8131bec9ec5c145e0074591777f6
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/18848
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Ewout van Bekkum <ewout@google.com>
diff --git a/pw_protobuf/public/pw_protobuf/serialized_size.h b/pw_protobuf/public/pw_protobuf/serialized_size.h
index aeb5a68..d671683 100644
--- a/pw_protobuf/public/pw_protobuf/serialized_size.h
+++ b/pw_protobuf/public/pw_protobuf/serialized_size.h
@@ -15,6 +15,7 @@
 
 #include <cstdint>
 
+#include "pw_protobuf/wire_format.h"
 #include "pw_varint/varint.h"
 
 namespace pw::protobuf {
@@ -43,4 +44,9 @@
 
 inline constexpr size_t kMaxSizeOfLength = varint::kMaxVarint32SizeBytes;
 
+constexpr size_t SizeOfFieldKey(uint32_t field_number) {
+  // The wiretype is ignored as this does not impact the serialized size.
+  return varint::EncodedSize(field_number << kFieldNumberShift);
+}
+
 }  // namespace pw::protobuf
diff --git a/pw_varint/public/pw_varint/varint.h b/pw_varint/public/pw_varint/varint.h
index 1b09bb2..9935967 100644
--- a/pw_varint/public/pw_varint/varint.h
+++ b/pw_varint/public/pw_varint/varint.h
@@ -134,13 +134,13 @@
 }
 
 // Returns a size of an integer when encoded as a varint.
-inline size_t EncodedSize(uint64_t integer) {
-  return pw_VarintEncodedSize(integer);
+constexpr size_t EncodedSize(uint64_t integer) {
+  return integer == 0 ? 1 : (64 - __builtin_clzll(integer) + 6) / 7;
 }
 
 // Returns a size of an signed integer when ZigZag encoded as a varint.
-inline size_t ZigZagEncodedSize(int64_t integer) {
-  return pw_VarintZigZagEncodedSize(integer);
+constexpr size_t ZigZagEncodedSize(int64_t integer) {
+  return EncodedSize(ZigZagEncode(integer));
 }
 
 }  // namespace varint
diff --git a/pw_varint/varint.cc b/pw_varint/varint.cc
index 1c21226..e2d1eb2 100644
--- a/pw_varint/varint.cc
+++ b/pw_varint/varint.cc
@@ -84,11 +84,11 @@
 }
 
 extern "C" size_t pw_VarintEncodedSize(uint64_t integer) {
-  return integer == 0 ? 1 : (64 - __builtin_clzll(integer) + 6) / 7;
+  return EncodedSize(integer);
 }
 
 extern "C" size_t pw_VarintZigZagEncodedSize(int64_t integer) {
-  return pw_VarintEncodedSize(ZigZagEncode(integer));
+  return ZigZagEncodedSize(integer);
 }
 
 }  // namespace varint