, and a type comparator Cmp, and some set of types
+// Args...:
+// Sort Args... using Cmp into SortedArgs..., then instantiate T
+// as Type.
+// Cmp should have a single constant `kValue` that is true if P < Q.
+template class T,
+ template class Cmp, typename... Args>
+struct WithSortedPack {
+ using Type = typename sorted_pack_detail::Sorted<
+ Cmp,
+ sorted_pack_detail::Typelist>::Result::template Instantiate;
+};
+
+} // namespace grpc_core
+
+#endif // GRPC_CORE_LIB_GPRPP_SORTED_PACK_H
diff --git a/src/core/lib/gprpp/table.h b/src/core/lib/gprpp/table.h
index f8e0128bd17..5cf6c788420 100644
--- a/src/core/lib/gprpp/table.h
+++ b/src/core/lib/gprpp/table.h
@@ -218,7 +218,7 @@ class Table {
// Check if this table has index I.
template
- absl::enable_if_t < I has() const {
+ absl::enable_if_t<(I < sizeof...(Ts)), bool> has() const {
return present_bits_.is_set(I);
}
@@ -317,6 +317,14 @@ class Table {
ForEachImpl(std::move(f), absl::make_index_sequence());
}
+ // Iterate through each set field in the table if it exists in Vs, in the
+ // order of Vs.
+ template
+ void ForEachIn(F f) const {
+ ForEachImpl(std::move(f),
+ absl::index_sequence()...>());
+ }
+
// Count the number of set fields in the table
size_t count() const { return present_bits_.count(); }
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
index 71e0394cac2..2df1a77e5e5 100644
--- a/src/core/lib/transport/metadata_batch.h
+++ b/src/core/lib/transport/metadata_batch.h
@@ -40,7 +40,7 @@
#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/gprpp/chunked_vector.h"
-#include "src/core/lib/gprpp/table.h"
+#include "src/core/lib/gprpp/packed_table.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
@@ -93,7 +93,7 @@ struct ContentTypeMetadata {
// gRPC says that content-type can be application/grpc[;something]
// Core has only ever verified the prefix.
// IF we want to start verifying more, we can expand this type.
- enum ValueType {
+ enum ValueType : uint8_t {
kApplicationGrpc,
kEmpty,
kInvalid,
@@ -112,7 +112,7 @@ struct ContentTypeMetadata {
// scheme metadata trait.
struct HttpSchemeMetadata {
static constexpr bool kRepeatable = false;
- enum ValueType {
+ enum ValueType : uint8_t {
kHttp,
kHttps,
kInvalid,
@@ -134,7 +134,7 @@ struct HttpSchemeMetadata {
// method metadata trait.
struct HttpMethodMetadata {
static constexpr bool kRepeatable = false;
- enum ValueType {
+ enum ValueType : uint8_t {
kPost,
kGet,
kPut,
@@ -1045,7 +1045,9 @@ class MetadataMap {
// void Encode(string_view key, Slice value);
template
void Encode(Encoder* encoder) const {
- table_.ForEach(metadata_detail::EncodeWrapper{encoder});
+ table_.template ForEachIn,
+ Value...>(
+ metadata_detail::EncodeWrapper{encoder});
for (const auto& unk : unknown_) {
encoder->Encode(unk.first, unk.second);
}
@@ -1222,7 +1224,7 @@ class MetadataMap {
using Value = metadata_detail::Value;
// Table of known metadata types.
- Table...> table_;
+ PackedTable...> table_;
metadata_detail::UnknownMap unknown_;
};
diff --git a/test/core/gprpp/BUILD b/test/core/gprpp/BUILD
index 4e95352fa15..5897573760b 100644
--- a/test/core/gprpp/BUILD
+++ b/test/core/gprpp/BUILD
@@ -355,6 +355,18 @@ grpc_cc_test(
],
)
+grpc_cc_test(
+ name = "sorted_pack_test",
+ srcs = ["sorted_pack_test.cc"],
+ external_deps = ["gtest"],
+ language = "c++",
+ uses_event_engine = False,
+ uses_polling = False,
+ deps = [
+ "//:sorted_pack",
+ ],
+)
+
grpc_cc_test(
name = "unique_type_name_test",
srcs = ["unique_type_name_test.cc"],
diff --git a/test/core/gprpp/sorted_pack_test.cc b/test/core/gprpp/sorted_pack_test.cc
new file mode 100644
index 00000000000..4d8467e3fbc
--- /dev/null
+++ b/test/core/gprpp/sorted_pack_test.cc
@@ -0,0 +1,70 @@
+// Copyright 2022 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/core/lib/gprpp/sorted_pack.h"
+
+#include
+#include
+
+#include
+
+using grpc_core::WithSortedPack;
+
+template
+struct Int {
+ int value() const { return I; }
+};
+
+template
+struct Cmp;
+template
+struct Cmp, Int> {
+ static constexpr bool kValue = A < B;
+};
+
+template
+struct VecMaker {
+ static std::vector Make() { return {Args().value()...}; }
+};
+
+template
+std::vector TestVec() {
+ return WithSortedPack...>::Type::Make();
+}
+
+TEST(SortedPackTest, Empty) { EXPECT_EQ(TestVec<>(), std::vector{}); }
+
+TEST(SortedPackTest, LenOne) {
+ EXPECT_EQ((TestVec<1>()), (std::vector{1}));
+ EXPECT_EQ((TestVec<2>()), (std::vector{2}));
+}
+
+TEST(SortedPackTest, Len2) {
+ EXPECT_EQ((TestVec<1, 2>()), (std::vector{1, 2}));
+ EXPECT_EQ((TestVec<2, 1>()), (std::vector{1, 2}));
+}
+
+TEST(SortedPackTest, Len3) {
+ EXPECT_EQ((TestVec<1, 2, 3>()), (std::vector{1, 2, 3}));
+ EXPECT_EQ((TestVec<1, 3, 2>()), (std::vector{1, 2, 3}));
+ EXPECT_EQ((TestVec<2, 1, 3>()), (std::vector{1, 2, 3}));
+ EXPECT_EQ((TestVec<2, 3, 1>()), (std::vector{1, 2, 3}));
+ EXPECT_EQ((TestVec<3, 1, 2>()), (std::vector{1, 2, 3}));
+ EXPECT_EQ((TestVec<3, 2, 1>()), (std::vector{1, 2, 3}));
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index daf08b1ba26..6a9060a29ce 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -2049,9 +2049,11 @@ src/core/lib/gprpp/mpscq.h \
src/core/lib/gprpp/no_destruct.h \
src/core/lib/gprpp/orphanable.h \
src/core/lib/gprpp/overload.h \
+src/core/lib/gprpp/packed_table.h \
src/core/lib/gprpp/ref_counted.h \
src/core/lib/gprpp/ref_counted_ptr.h \
src/core/lib/gprpp/single_set_ptr.h \
+src/core/lib/gprpp/sorted_pack.h \
src/core/lib/gprpp/stat.h \
src/core/lib/gprpp/stat_posix.cc \
src/core/lib/gprpp/stat_windows.cc \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index ce9f30909b3..91b6aa35d97 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1841,9 +1841,11 @@ src/core/lib/gprpp/mpscq.h \
src/core/lib/gprpp/no_destruct.h \
src/core/lib/gprpp/orphanable.h \
src/core/lib/gprpp/overload.h \
+src/core/lib/gprpp/packed_table.h \
src/core/lib/gprpp/ref_counted.h \
src/core/lib/gprpp/ref_counted_ptr.h \
src/core/lib/gprpp/single_set_ptr.h \
+src/core/lib/gprpp/sorted_pack.h \
src/core/lib/gprpp/stat.h \
src/core/lib/gprpp/stat_posix.cc \
src/core/lib/gprpp/stat_windows.cc \
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index b841ee8cc5e..ac222f27e86 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -6123,6 +6123,30 @@
],
"uses_polling": true
},
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "sorted_pack_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "uses_polling": false
+ },
{
"args": [],
"benchmark": false,