1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #ifndef GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
20 #define GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <stdlib.h>
25 
26 #include <cstdint>
27 #include <string>
28 #include <type_traits>
29 #include <utility>
30 
31 #include "absl/container/inlined_vector.h"
32 #include "absl/functional/function_ref.h"
33 #include "absl/meta/type_traits.h"
34 #include "absl/strings/numbers.h"
35 #include "absl/strings/string_view.h"
36 #include "absl/types/optional.h"
37 
38 #include <grpc/impl/compression_types.h>
39 #include <grpc/status.h>
40 #include <grpc/support/log.h>
41 
42 #include "src/core/lib/compression/compression_internal.h"
43 #include "src/core/lib/gprpp/chunked_vector.h"
44 #include "src/core/lib/gprpp/packed_table.h"
45 #include "src/core/lib/gprpp/time.h"
46 #include "src/core/lib/resource_quota/arena.h"
47 #include "src/core/lib/slice/slice.h"
48 #include "src/core/lib/transport/custom_metadata.h"
49 #include "src/core/lib/transport/metadata_compression_traits.h"
50 #include "src/core/lib/transport/parsed_metadata.h"
51 #include "src/core/lib/transport/simple_slice_based_metadata.h"
52 
53 namespace grpc_core {
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 // Metadata traits
57 
58 // Given a metadata key and a value, return the encoded size.
59 // Defaults to calling the key's Encode() method and then calculating the size
60 // of that, but can be overridden for specific keys if there's a better way of
61 // doing this.
62 // May return 0 if the size is unknown/unknowable.
63 template <typename Key>
EncodedSizeOfKey(Key,const typename Key::ValueType & value)64 size_t EncodedSizeOfKey(Key, const typename Key::ValueType& value) {
65   return Key::Encode(value).size();
66 }
67 
68 // grpc-timeout metadata trait.
69 // ValueType is defined as Timestamp - an absolute timestamp (i.e. a
70 // deadline!), that is converted to a duration by transports before being
71 // sent.
72 // TODO(ctiller): Move this elsewhere. During the transition we need to be able
73 // to name this in MetadataMap, but ultimately once the transition is done we
74 // should not need to.
75 struct GrpcTimeoutMetadata {
76   static constexpr bool kRepeatable = false;
77   using ValueType = Timestamp;
78   using MementoType = Duration;
79   using CompressionTraits = TimeoutCompressor;
keyGrpcTimeoutMetadata80   static absl::string_view key() { return "grpc-timeout"; }
81   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error);
82   static ValueType MementoToValue(MementoType timeout);
83   static Slice Encode(ValueType x);
DisplayValueGrpcTimeoutMetadata84   static std::string DisplayValue(ValueType x) { return x.ToString(); }
DisplayMementoGrpcTimeoutMetadata85   static std::string DisplayMemento(MementoType x) { return x.ToString(); }
86 };
87 
88 // TE metadata trait.
89 struct TeMetadata {
90   static constexpr bool kRepeatable = false;
91   // HTTP2 says that TE can either be empty or "trailers".
92   // Empty means this trait is not included, "trailers" means kTrailers, and
93   // kInvalid is used to remember an invalid value.
94   enum ValueType : uint8_t {
95     kTrailers,
96     kInvalid,
97   };
98   using MementoType = ValueType;
99   using CompressionTraits = KnownValueCompressor<ValueType, kTrailers>;
keyTeMetadata100   static absl::string_view key() { return "te"; }
101   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error);
MementoToValueTeMetadata102   static ValueType MementoToValue(MementoType te) { return te; }
EncodeTeMetadata103   static StaticSlice Encode(ValueType x) {
104     GPR_ASSERT(x == kTrailers);
105     return StaticSlice::FromStaticString("trailers");
106   }
107   static const char* DisplayValue(ValueType te);
DisplayMementoTeMetadata108   static const char* DisplayMemento(MementoType te) { return DisplayValue(te); }
109 };
110 
EncodedSizeOfKey(TeMetadata,TeMetadata::ValueType x)111 inline size_t EncodedSizeOfKey(TeMetadata, TeMetadata::ValueType x) {
112   return x == TeMetadata::kTrailers ? 8 : 0;
113 }
114 
115 // content-type metadata trait.
116 struct ContentTypeMetadata {
117   static constexpr bool kRepeatable = false;
118   // gRPC says that content-type can be application/grpc[;something]
119   // Core has only ever verified the prefix.
120   // IF we want to start verifying more, we can expand this type.
121   enum ValueType : uint8_t {
122     kApplicationGrpc,
123     kEmpty,
124     kInvalid,
125   };
126   using MementoType = ValueType;
127   using CompressionTraits = KnownValueCompressor<ValueType, kApplicationGrpc>;
keyContentTypeMetadata128   static absl::string_view key() { return "content-type"; }
129   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error);
MementoToValueContentTypeMetadata130   static ValueType MementoToValue(MementoType content_type) {
131     return content_type;
132   }
133 
134   static StaticSlice Encode(ValueType x);
135   static const char* DisplayValue(ValueType content_type);
DisplayMementoContentTypeMetadata136   static const char* DisplayMemento(ValueType content_type) {
137     return DisplayValue(content_type);
138   }
139 };
140 
141 // scheme metadata trait.
142 struct HttpSchemeMetadata {
143   static constexpr bool kRepeatable = false;
144   enum ValueType : uint8_t {
145     kHttp,
146     kHttps,
147     kInvalid,
148   };
149   using MementoType = ValueType;
150   using CompressionTraits = HttpSchemeCompressor;
keyHttpSchemeMetadata151   static absl::string_view key() { return ":scheme"; }
ParseMementoHttpSchemeMetadata152   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) {
153     return Parse(value.as_string_view(), on_error);
154   }
155   static ValueType Parse(absl::string_view value,
156                          MetadataParseErrorFn on_error);
MementoToValueHttpSchemeMetadata157   static ValueType MementoToValue(MementoType content_type) {
158     return content_type;
159   }
160   static StaticSlice Encode(ValueType x);
161   static const char* DisplayValue(ValueType content_type);
DisplayMementoHttpSchemeMetadata162   static const char* DisplayMemento(MementoType content_type) {
163     return DisplayValue(content_type);
164   }
165 };
166 
167 size_t EncodedSizeOfKey(HttpSchemeMetadata, HttpSchemeMetadata::ValueType x);
168 
169 // method metadata trait.
170 struct HttpMethodMetadata {
171   static constexpr bool kRepeatable = false;
172   enum ValueType : uint8_t {
173     kPost,
174     kGet,
175     kPut,
176     kInvalid,
177   };
178   using MementoType = ValueType;
179   using CompressionTraits = HttpMethodCompressor;
keyHttpMethodMetadata180   static absl::string_view key() { return ":method"; }
181   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error);
MementoToValueHttpMethodMetadata182   static ValueType MementoToValue(MementoType content_type) {
183     return content_type;
184   }
185   static StaticSlice Encode(ValueType x);
186   static const char* DisplayValue(ValueType content_type);
DisplayMementoHttpMethodMetadata187   static const char* DisplayMemento(MementoType content_type) {
188     return DisplayValue(content_type);
189   }
190 };
191 
192 // Base type for metadata pertaining to a single compression algorithm
193 // (e.g., "grpc-encoding").
194 struct CompressionAlgorithmBasedMetadata {
195   using ValueType = grpc_compression_algorithm;
196   using MementoType = ValueType;
197   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error);
MementoToValueCompressionAlgorithmBasedMetadata198   static ValueType MementoToValue(MementoType x) { return x; }
EncodeCompressionAlgorithmBasedMetadata199   static Slice Encode(ValueType x) {
200     GPR_ASSERT(x != GRPC_COMPRESS_ALGORITHMS_COUNT);
201     return Slice::FromStaticString(CompressionAlgorithmAsString(x));
202   }
DisplayValueCompressionAlgorithmBasedMetadata203   static const char* DisplayValue(ValueType x) {
204     if (const char* p = CompressionAlgorithmAsString(x)) {
205       return p;
206     } else {
207       return "<discarded-invalid-value>";
208     }
209   }
DisplayMementoCompressionAlgorithmBasedMetadata210   static const char* DisplayMemento(MementoType x) { return DisplayValue(x); }
211 };
212 
213 // grpc-encoding metadata trait.
214 struct GrpcEncodingMetadata : public CompressionAlgorithmBasedMetadata {
215   static constexpr bool kRepeatable = false;
216   using CompressionTraits =
217       SmallIntegralValuesCompressor<GRPC_COMPRESS_ALGORITHMS_COUNT>;
keyGrpcEncodingMetadata218   static absl::string_view key() { return "grpc-encoding"; }
219 };
220 
221 // grpc-internal-encoding-request metadata trait.
222 struct GrpcInternalEncodingRequest : public CompressionAlgorithmBasedMetadata {
223   static constexpr bool kRepeatable = false;
224   using CompressionTraits = NoCompressionCompressor;
keyGrpcInternalEncodingRequest225   static absl::string_view key() { return "grpc-internal-encoding-request"; }
226 };
227 
228 // grpc-accept-encoding metadata trait.
229 struct GrpcAcceptEncodingMetadata {
230   static constexpr bool kRepeatable = false;
keyGrpcAcceptEncodingMetadata231   static absl::string_view key() { return "grpc-accept-encoding"; }
232   using ValueType = CompressionAlgorithmSet;
233   using MementoType = ValueType;
234   using CompressionTraits = StableValueCompressor;
ParseMementoGrpcAcceptEncodingMetadata235   static MementoType ParseMemento(Slice value, MetadataParseErrorFn) {
236     return CompressionAlgorithmSet::FromString(value.as_string_view());
237   }
MementoToValueGrpcAcceptEncodingMetadata238   static ValueType MementoToValue(MementoType x) { return x; }
EncodeGrpcAcceptEncodingMetadata239   static Slice Encode(ValueType x) { return x.ToSlice(); }
DisplayValueGrpcAcceptEncodingMetadata240   static absl::string_view DisplayValue(ValueType x) { return x.ToString(); }
DisplayMementoGrpcAcceptEncodingMetadata241   static absl::string_view DisplayMemento(MementoType x) {
242     return DisplayValue(x);
243   }
244 };
245 
246 // user-agent metadata trait.
247 struct UserAgentMetadata : public SimpleSliceBasedMetadata {
248   static constexpr bool kRepeatable = false;
249   using CompressionTraits = StableValueCompressor;
keyUserAgentMetadata250   static absl::string_view key() { return "user-agent"; }
251 };
252 
253 // grpc-message metadata trait.
254 struct GrpcMessageMetadata : public SimpleSliceBasedMetadata {
255   static constexpr bool kRepeatable = false;
256   using CompressionTraits = NoCompressionCompressor;
keyGrpcMessageMetadata257   static absl::string_view key() { return "grpc-message"; }
258 };
259 
260 // host metadata trait.
261 struct HostMetadata : public SimpleSliceBasedMetadata {
262   static constexpr bool kRepeatable = false;
263   using CompressionTraits = NoCompressionCompressor;
keyHostMetadata264   static absl::string_view key() { return "host"; }
265 };
266 
267 // endpoint-load-metrics-bin metadata trait.
268 struct EndpointLoadMetricsBinMetadata : public SimpleSliceBasedMetadata {
269   static constexpr bool kRepeatable = false;
270   using CompressionTraits = NoCompressionCompressor;
keyEndpointLoadMetricsBinMetadata271   static absl::string_view key() { return "endpoint-load-metrics-bin"; }
272 };
273 
274 // grpc-server-stats-bin metadata trait.
275 struct GrpcServerStatsBinMetadata : public SimpleSliceBasedMetadata {
276   static constexpr bool kRepeatable = false;
277   using CompressionTraits = NoCompressionCompressor;
keyGrpcServerStatsBinMetadata278   static absl::string_view key() { return "grpc-server-stats-bin"; }
279 };
280 
281 // grpc-trace-bin metadata trait.
282 struct GrpcTraceBinMetadata : public SimpleSliceBasedMetadata {
283   static constexpr bool kRepeatable = false;
284   using CompressionTraits = FrequentKeyWithNoValueCompressionCompressor;
keyGrpcTraceBinMetadata285   static absl::string_view key() { return "grpc-trace-bin"; }
286 };
287 
288 // grpc-tags-bin metadata trait.
289 struct GrpcTagsBinMetadata : public SimpleSliceBasedMetadata {
290   static constexpr bool kRepeatable = false;
291   using CompressionTraits = FrequentKeyWithNoValueCompressionCompressor;
keyGrpcTagsBinMetadata292   static absl::string_view key() { return "grpc-tags-bin"; }
293 };
294 
295 // :authority metadata trait.
296 struct HttpAuthorityMetadata : public SimpleSliceBasedMetadata {
297   static constexpr bool kRepeatable = false;
298   using CompressionTraits = SmallSetOfValuesCompressor;
keyHttpAuthorityMetadata299   static absl::string_view key() { return ":authority"; }
300 };
301 
302 // :path metadata trait.
303 struct HttpPathMetadata : public SimpleSliceBasedMetadata {
304   static constexpr bool kRepeatable = false;
305   using CompressionTraits = SmallSetOfValuesCompressor;
keyHttpPathMetadata306   static absl::string_view key() { return ":path"; }
307 };
308 
309 // We separate SimpleIntBasedMetadata into two pieces: one that does not
310 // depend on the invalid value, and one that does. This allows the compiler to
311 // easily see the functions that are shared, and helps reduce code bloat here.
312 template <typename Int>
313 struct SimpleIntBasedMetadataBase {
314   using ValueType = Int;
315   using MementoType = Int;
MementoToValueSimpleIntBasedMetadataBase316   static ValueType MementoToValue(MementoType value) { return value; }
EncodeSimpleIntBasedMetadataBase317   static Slice Encode(ValueType x) { return Slice::FromInt64(x); }
DisplayValueSimpleIntBasedMetadataBase318   static Int DisplayValue(ValueType x) { return x; }
DisplayMementoSimpleIntBasedMetadataBase319   static Int DisplayMemento(MementoType x) { return x; }
320 };
321 
322 template <typename Int, Int kInvalidValue>
323 struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> {
invalid_valueSimpleIntBasedMetadata324   static constexpr Int invalid_value() { return kInvalidValue; }
ParseMementoSimpleIntBasedMetadata325   static Int ParseMemento(Slice value, MetadataParseErrorFn on_error) {
326     Int out;
327     if (!absl::SimpleAtoi(value.as_string_view(), &out)) {
328       on_error("not an integer", value);
329       out = kInvalidValue;
330     }
331     return out;
332   }
333 };
334 
335 // grpc-status metadata trait.
336 struct GrpcStatusMetadata
337     : public SimpleIntBasedMetadata<grpc_status_code, GRPC_STATUS_UNKNOWN> {
338   static constexpr bool kRepeatable = false;
339   using CompressionTraits = SmallIntegralValuesCompressor<16>;
keyGrpcStatusMetadata340   static absl::string_view key() { return "grpc-status"; }
341 };
342 
343 // grpc-previous-rpc-attempts metadata trait.
344 struct GrpcPreviousRpcAttemptsMetadata
345     : public SimpleIntBasedMetadata<uint32_t, 0> {
346   static constexpr bool kRepeatable = false;
347   using CompressionTraits = NoCompressionCompressor;
keyGrpcPreviousRpcAttemptsMetadata348   static absl::string_view key() { return "grpc-previous-rpc-attempts"; }
349 };
350 
351 // grpc-retry-pushback-ms metadata trait.
352 struct GrpcRetryPushbackMsMetadata {
353   static constexpr bool kRepeatable = false;
keyGrpcRetryPushbackMsMetadata354   static absl::string_view key() { return "grpc-retry-pushback-ms"; }
355   using ValueType = Duration;
356   using MementoType = Duration;
357   using CompressionTraits = NoCompressionCompressor;
MementoToValueGrpcRetryPushbackMsMetadata358   static ValueType MementoToValue(MementoType x) { return x; }
EncodeGrpcRetryPushbackMsMetadata359   static Slice Encode(Duration x) { return Slice::FromInt64(x.millis()); }
DisplayValueGrpcRetryPushbackMsMetadata360   static int64_t DisplayValue(Duration x) { return x.millis(); }
DisplayMementoGrpcRetryPushbackMsMetadata361   static int64_t DisplayMemento(Duration x) { return DisplayValue(x); }
362   static Duration ParseMemento(Slice value, MetadataParseErrorFn on_error);
363 };
364 
365 // :status metadata trait.
366 // TODO(ctiller): consider moving to uint16_t
367 struct HttpStatusMetadata : public SimpleIntBasedMetadata<uint32_t, 0> {
368   static constexpr bool kRepeatable = false;
369   using CompressionTraits = HttpStatusCompressor;
keyHttpStatusMetadata370   static absl::string_view key() { return ":status"; }
371 };
372 
373 // "secret" metadata trait used to pass load balancing token between filters.
374 // This should not be exposed outside of gRPC core.
375 class GrpcLbClientStats;
376 
377 struct GrpcLbClientStatsMetadata {
378   static constexpr bool kRepeatable = false;
keyGrpcLbClientStatsMetadata379   static absl::string_view key() { return "grpclb_client_stats"; }
380   using ValueType = GrpcLbClientStats*;
381   using MementoType = ValueType;
382   using CompressionTraits = NoCompressionCompressor;
MementoToValueGrpcLbClientStatsMetadata383   static ValueType MementoToValue(MementoType value) { return value; }
EncodeGrpcLbClientStatsMetadata384   static Slice Encode(ValueType) { abort(); }
DisplayValueGrpcLbClientStatsMetadata385   static const char* DisplayValue(ValueType) { return "<internal-lb-stats>"; }
DisplayMementoGrpcLbClientStatsMetadata386   static const char* DisplayMemento(MementoType) {
387     return "<internal-lb-stats>";
388   }
ParseMementoGrpcLbClientStatsMetadata389   static MementoType ParseMemento(Slice, MetadataParseErrorFn) {
390     return nullptr;
391   }
392 };
393 
EncodedSizeOfKey(GrpcLbClientStatsMetadata,GrpcLbClientStatsMetadata::ValueType)394 inline size_t EncodedSizeOfKey(GrpcLbClientStatsMetadata,
395                                GrpcLbClientStatsMetadata::ValueType) {
396   return 0;
397 }
398 
399 // lb-token metadata
400 struct LbTokenMetadata : public SimpleSliceBasedMetadata {
401   static constexpr bool kRepeatable = false;
402   using CompressionTraits = NoCompressionCompressor;
keyLbTokenMetadata403   static absl::string_view key() { return "lb-token"; }
404 };
405 
406 // lb-cost-bin metadata
407 struct LbCostBinMetadata {
408   static constexpr bool kRepeatable = true;
keyLbCostBinMetadata409   static absl::string_view key() { return "lb-cost-bin"; }
410   struct ValueType {
411     double cost;
412     std::string name;
413   };
414   using MementoType = ValueType;
415   using CompressionTraits = NoCompressionCompressor;
MementoToValueLbCostBinMetadata416   static ValueType MementoToValue(MementoType value) { return value; }
417   static Slice Encode(const ValueType& x);
418   static std::string DisplayValue(ValueType x);
DisplayMementoLbCostBinMetadata419   static std::string DisplayMemento(MementoType x) { return DisplayValue(x); }
420   static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error);
421 };
422 
423 // Annotation added by a transport to note whether a failed request was never
424 // placed on the wire, or never seen by a server.
425 struct GrpcStreamNetworkState {
DebugKeyGrpcStreamNetworkState426   static absl::string_view DebugKey() { return "GrpcStreamNetworkState"; }
427   static constexpr bool kRepeatable = false;
428   enum ValueType : uint8_t {
429     kNotSentOnWire,
430     kNotSeenByServer,
431   };
432   static std::string DisplayValue(ValueType x);
433 };
434 
435 // Annotation added by a server transport to note the peer making a request.
436 struct PeerString {
DebugKeyPeerString437   static absl::string_view DebugKey() { return "PeerString"; }
438   static constexpr bool kRepeatable = false;
439   using ValueType = Slice;
440   static std::string DisplayValue(const ValueType& x);
441 };
442 
443 // Annotation added by various systems to describe the reason for a failure.
444 struct GrpcStatusContext {
DebugKeyGrpcStatusContext445   static absl::string_view DebugKey() { return "GrpcStatusContext"; }
446   static constexpr bool kRepeatable = true;
447   using ValueType = std::string;
448   static const std::string& DisplayValue(const std::string& x);
449 };
450 
451 // Annotation added by a transport to note that the status came from the wire.
452 struct GrpcStatusFromWire {
DebugKeyGrpcStatusFromWire453   static absl::string_view DebugKey() { return "GrpcStatusFromWire"; }
454   static constexpr bool kRepeatable = false;
455   using ValueType = bool;
DisplayValueGrpcStatusFromWire456   static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
457 };
458 
459 // Annotation to denote that this call qualifies for cancelled=1 for the
460 // RECV_CLOSE_ON_SERVER op
461 struct GrpcCallWasCancelled {
DebugKeyGrpcCallWasCancelled462   static absl::string_view DebugKey() { return "GrpcCallWasCancelled"; }
463   static constexpr bool kRepeatable = false;
464   using ValueType = bool;
DisplayValueGrpcCallWasCancelled465   static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
466 };
467 
468 // Annotation added by client surface code to denote wait-for-ready state
469 struct WaitForReady {
470   struct ValueType {
471     bool value = false;
472     bool explicitly_set = false;
473   };
DebugKeyWaitForReady474   static absl::string_view DebugKey() { return "WaitForReady"; }
475   static constexpr bool kRepeatable = false;
476   static std::string DisplayValue(ValueType x);
477 };
478 
479 // Annotation added by a transport to note that server trailing metadata
480 // is a Trailers-Only response.
481 struct GrpcTrailersOnly {
DebugKeyGrpcTrailersOnly482   static absl::string_view DebugKey() { return "GrpcTrailersOnly"; }
483   static constexpr bool kRepeatable = false;
484   using ValueType = bool;
DisplayValueGrpcTrailersOnly485   static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
486 };
487 
488 namespace metadata_detail {
489 
490 // Build a key/value formatted debug string.
491 // Output looks like 'key1: value1, key2: value2'
492 // The string is expected to be readable, but not necessarily parsable.
493 class DebugStringBuilder {
494  public:
495   // Add one key/value pair to the output.
496   void Add(absl::string_view key, absl::string_view value);
497 
498   // Finalize the output and return the string.
499   // Subsequent Add calls are UB.
TakeOutput()500   std::string TakeOutput() { return std::move(out_); }
501 
502  private:
503   std::string out_;
504 };
505 
506 // IsEncodable: Given a trait, determine if that trait is encodable, or is
507 // just a value attached to a MetadataMap. We use the presence of the key()
508 // static method to determine if a trait is encodable or not - encodable
509 // traits have string names, and non-encodable traits do not.
510 template <typename Trait, typename Ignored = void>
511 struct IsEncodableTrait {
512   static const bool value = false;
513 };
514 
515 template <typename Trait>
516 struct IsEncodableTrait<Trait, absl::void_t<decltype(Trait::key())>> {
517   static const bool value = true;
518 };
519 
520 // Helper type - maps a string name to a trait.
521 template <typename MustBeVoid, typename... Traits>
522 struct NameLookup;
523 
524 template <typename Trait, typename... Traits>
525 struct NameLookup<absl::enable_if_t<IsEncodableTrait<Trait>::value, void>,
526                   Trait, Traits...> {
527   // Call op->Found(Trait()) if op->name == Trait::key() for some Trait in
528   // Traits. If not found, call op->NotFound().
529   template <typename Op>
530   static auto Lookup(absl::string_view key, Op* op)
531       -> decltype(op->Found(Trait())) {
532     if (key == Trait::key()) {
533       return op->Found(Trait());
534     }
535     return NameLookup<void, Traits...>::Lookup(key, op);
536   }
537 };
538 
539 template <typename Trait, typename... Traits>
540 struct NameLookup<absl::enable_if_t<!IsEncodableTrait<Trait>::value, void>,
541                   Trait, Traits...> {
542   template <typename Op>
543   static auto Lookup(absl::string_view key, Op* op)
544       -> decltype(NameLookup<void, Traits...>::Lookup(key, op)) {
545     return NameLookup<void, Traits...>::Lookup(key, op);
546   }
547 };
548 
549 template <>
550 struct NameLookup<void> {
551   template <typename Op>
552   static auto Lookup(absl::string_view key, Op* op)
553       -> decltype(op->NotFound(key)) {
554     return op->NotFound(key);
555   }
556 };
557 
558 // Helper to take a slice to a memento to a value.
559 // By splitting this part out we can scale code size as the number of
560 // (memento, value) types, rather than as the number of traits.
561 template <typename ParseMementoFn, typename MementoToValueFn>
562 struct ParseValue {
563   template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value>
564   static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value,
565                                            MetadataParseErrorFn on_error)
566       -> decltype(memento_to_value(parse_memento(std::move(*value),
567                                                  on_error))) {
568     return memento_to_value(parse_memento(std::move(*value), on_error));
569   }
570 };
571 
572 // This is an "Op" type for NameLookup.
573 // Used for MetadataMap::Parse, its Found/NotFound methods turn a slice into a
574 // ParsedMetadata object.
575 template <typename Container>
576 class ParseHelper {
577  public:
578   ParseHelper(Slice value, MetadataParseErrorFn on_error, size_t transport_size)
579       : value_(std::move(value)),
580         on_error_(on_error),
581         transport_size_(transport_size) {}
582 
583   template <typename Trait>
584   GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) {
585     return ParsedMetadata<Container>(
586         trait,
587         ParseValueToMemento<typename Trait::MementoType, Trait::ParseMemento>(),
588         static_cast<uint32_t>(transport_size_));
589   }
590 
591   GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> NotFound(
592       absl::string_view key) {
593     return ParsedMetadata<Container>(
594         typename ParsedMetadata<Container>::FromSlicePair{},
595         Slice::FromCopiedString(key), std::move(value_), transport_size_);
596   }
597 
598  private:
599   template <typename T, T (*parse_memento)(Slice, MetadataParseErrorFn)>
600   GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() {
601     return parse_memento(std::move(value_), on_error_);
602   }
603 
604   Slice value_;
605   MetadataParseErrorFn on_error_;
606   const size_t transport_size_;
607 };
608 
609 // This is an "Op" type for NameLookup.
610 // Used for MetadataMap::Append, its Found/NotFound methods turn a slice into
611 // a value and add it to a container.
612 template <typename Container>
613 class AppendHelper {
614  public:
615   AppendHelper(Container* container, Slice value, MetadataParseErrorFn on_error)
616       : container_(container), value_(std::move(value)), on_error_(on_error) {}
617 
618   template <typename Trait>
619   GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
620     container_->Set(
621         trait, ParseValue<decltype(Trait::ParseMemento),
622                           decltype(Trait::MementoToValue)>::
623                    template Parse<Trait::ParseMemento, Trait::MementoToValue>(
624                        &value_, on_error_));
625   }
626 
627   GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
628     container_->unknown_.Append(key, std::move(value_));
629   }
630 
631  private:
632   Container* const container_;
633   Slice value_;
634   MetadataParseErrorFn on_error_;
635 };
636 
637 // This is an "Op" type for NameLookup.
638 // Used for MetadataMap::Remove, its Found/NotFound methods remove a key from
639 // the container.
640 template <typename Container>
641 class RemoveHelper {
642  public:
643   explicit RemoveHelper(Container* container) : container_(container) {}
644 
645   template <typename Trait>
646   GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
647     container_->Remove(trait);
648   }
649 
650   GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
651     container_->unknown_.Remove(key);
652   }
653 
654  private:
655   Container* const container_;
656 };
657 
658 // This is an "Op" type for NameLookup.
659 // Used for MetadataMap::GetStringValue, its Found/NotFound methods generated
660 // a string value from the container.
661 template <typename Container>
662 class GetStringValueHelper {
663  public:
664   explicit GetStringValueHelper(const Container* container,
665                                 std::string* backing)
666       : container_(container), backing_(backing) {}
667 
668   template <typename Trait>
669   GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
670       Trait::kRepeatable == false &&
671           std::is_same<Slice, typename Trait::ValueType>::value,
672       absl::optional<absl::string_view>>
673   Found(Trait) {
674     const auto* value = container_->get_pointer(Trait());
675     if (value == nullptr) return absl::nullopt;
676     return value->as_string_view();
677   }
678 
679   template <typename Trait>
680   GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
681       Trait::kRepeatable == true &&
682           !std::is_same<Slice, typename Trait::ValueType>::value,
683       absl::optional<absl::string_view>>
684   Found(Trait) {
685     const auto* value = container_->get_pointer(Trait());
686     if (value == nullptr) return absl::nullopt;
687     backing_->clear();
688     for (const auto& v : *value) {
689       if (!backing_->empty()) backing_->push_back(',');
690       auto new_segment = Trait::Encode(v);
691       backing_->append(new_segment.begin(), new_segment.end());
692     }
693     return *backing_;
694   }
695 
696   template <typename Trait>
697   GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
698       Trait::kRepeatable == false &&
699           !std::is_same<Slice, typename Trait::ValueType>::value,
700       absl::optional<absl::string_view>>
701   Found(Trait) {
702     const auto* value = container_->get_pointer(Trait());
703     if (value == nullptr) return absl::nullopt;
704     *backing_ = std::string(Trait::Encode(*value).as_string_view());
705     return *backing_;
706   }
707 
708   GPR_ATTRIBUTE_NOINLINE absl::optional<absl::string_view> NotFound(
709       absl::string_view key) {
710     return container_->unknown_.GetStringValue(key, backing_);
711   }
712 
713  private:
714   const Container* const container_;
715   std::string* backing_;
716 };
717 
718 // Sink for key value logs
719 using LogFn = absl::FunctionRef<void(absl::string_view, absl::string_view)>;
720 
721 template <typename T>
722 struct AdaptDisplayValueToLog {
723   static std::string ToString(const T& value) { return std::to_string(value); }
724 };
725 
726 template <>
727 struct AdaptDisplayValueToLog<std::string> {
728   static std::string ToString(const std::string& value) { return value; }
729 };
730 
731 template <>
732 struct AdaptDisplayValueToLog<const std::string&> {
733   static std::string ToString(const std::string& value) { return value; }
734 };
735 
736 template <>
737 struct AdaptDisplayValueToLog<absl::string_view> {
738   static std::string ToString(absl::string_view value) {
739     return std::string(value);
740   }
741 };
742 
743 template <>
744 struct AdaptDisplayValueToLog<Slice> {
745   static std::string ToString(Slice value) {
746     return std::string(value.as_string_view());
747   }
748 };
749 
750 template <>
751 struct AdaptDisplayValueToLog<const char*> {
752   static std::string ToString(const char* value) { return std::string(value); }
753 };
754 
755 template <>
756 struct AdaptDisplayValueToLog<StaticSlice> {
757   static absl::string_view ToString(StaticSlice value) {
758     return value.as_string_view();
759   }
760 };
761 
762 template <typename T, typename U, typename V>
763 GPR_ATTRIBUTE_NOINLINE void LogKeyValueTo(absl::string_view key, const T& value,
764                                           V (*display_value)(U), LogFn log_fn) {
765   log_fn(key, AdaptDisplayValueToLog<V>::ToString(display_value(value)));
766 }
767 
768 // Generate a strong type for metadata values per trait.
769 template <typename Which, typename Ignored = void>
770 struct Value;
771 
772 template <typename Which>
773 struct Value<Which, absl::enable_if_t<Which::kRepeatable == false &&
774                                           IsEncodableTrait<Which>::value,
775                                       void>> {
776   Value() = default;
777   explicit Value(const typename Which::ValueType& value) : value(value) {}
778   explicit Value(typename Which::ValueType&& value)
779       : value(std::forward<typename Which::ValueType>(value)) {}
780   Value(const Value&) = delete;
781   Value& operator=(const Value&) = delete;
782   Value(Value&&) noexcept = default;
783   Value& operator=(Value&& other) noexcept {
784     value = std::move(other.value);
785     return *this;
786   }
787   template <typename Encoder>
788   void EncodeTo(Encoder* encoder) const {
789     encoder->Encode(Which(), value);
790   }
791   template <typename Encoder>
792   void VisitWith(Encoder* encoder) const {
793     return EncodeTo(encoder);
794   }
795   void LogTo(LogFn log_fn) const {
796     LogKeyValueTo(Which::key(), value, Which::DisplayValue, log_fn);
797   }
798   using StorageType = typename Which::ValueType;
799   GPR_NO_UNIQUE_ADDRESS StorageType value;
800 };
801 
802 template <typename Which>
803 struct Value<Which, absl::enable_if_t<Which::kRepeatable == false &&
804                                           !IsEncodableTrait<Which>::value,
805                                       void>> {
806   Value() = default;
807   explicit Value(const typename Which::ValueType& value) : value(value) {}
808   explicit Value(typename Which::ValueType&& value)
809       : value(std::forward<typename Which::ValueType>(value)) {}
810   Value(const Value&) = delete;
811   Value& operator=(const Value&) = delete;
812   Value(Value&&) noexcept = default;
813   Value& operator=(Value&& other) noexcept {
814     value = std::move(other.value);
815     return *this;
816   }
817   template <typename Encoder>
818   void EncodeTo(Encoder*) const {}
819   template <typename Encoder>
820   void VisitWith(Encoder* encoder) const {
821     encoder->Encode(Which(), value);
822   }
823   void LogTo(LogFn log_fn) const {
824     LogKeyValueTo(Which::DebugKey(), value, Which::DisplayValue, log_fn);
825   }
826   using StorageType = typename Which::ValueType;
827   GPR_NO_UNIQUE_ADDRESS StorageType value;
828 };
829 
830 template <typename Which>
831 struct Value<Which, absl::enable_if_t<Which::kRepeatable == true &&
832                                           IsEncodableTrait<Which>::value,
833                                       void>> {
834   Value() = default;
835   explicit Value(const typename Which::ValueType& value) {
836     this->value.push_back(value);
837   }
838   explicit Value(typename Which::ValueType&& value) {
839     this->value.emplace_back(std::forward<typename Which::ValueType>(value));
840   }
841   Value(const Value&) = delete;
842   Value& operator=(const Value&) = delete;
843   Value(Value&& other) noexcept : value(std::move(other.value)) {}
844   Value& operator=(Value&& other) noexcept {
845     value = std::move(other.value);
846     return *this;
847   }
848   template <typename Encoder>
849   void EncodeTo(Encoder* encoder) const {
850     for (const auto& v : value) {
851       encoder->Encode(Which(), v);
852     }
853   }
854   template <typename Encoder>
855   void VisitWith(Encoder* encoder) const {
856     return EncodeTo(encoder);
857   }
858   void LogTo(LogFn log_fn) const {
859     for (const auto& v : value) {
860       LogKeyValueTo(Which::key(), v, Which::Encode, log_fn);
861     }
862   }
863   using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
864   StorageType value;
865 };
866 
867 template <typename Which>
868 struct Value<Which, absl::enable_if_t<Which::kRepeatable == true &&
869                                           !IsEncodableTrait<Which>::value,
870                                       void>> {
871   Value() = default;
872   explicit Value(const typename Which::ValueType& value) {
873     this->value.push_back(value);
874   }
875   explicit Value(typename Which::ValueType&& value) {
876     this->value.emplace_back(std::forward<typename Which::ValueType>(value));
877   }
878   Value(const Value&) = delete;
879   Value& operator=(const Value&) = delete;
880   Value(Value&& other) noexcept : value(std::move(other.value)) {}
881   Value& operator=(Value&& other) noexcept {
882     value = std::move(other.value);
883     return *this;
884   }
885   template <typename Encoder>
886   void EncodeTo(Encoder*) const {}
887   template <typename Encoder>
888   void VisitWith(Encoder* encoder) const {
889     for (const auto& v : value) {
890       encoder->Encode(Which(), v);
891     }
892   }
893   void LogTo(LogFn log_fn) const {
894     for (const auto& v : value) {
895       LogKeyValueTo(Which::DebugKey(), v, Which::DisplayValue, log_fn);
896     }
897   }
898   using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
899   StorageType value;
900 };
901 
902 // Encoder to copy some metadata
903 template <typename Output>
904 class CopySink {
905  public:
906   explicit CopySink(Output* dst) : dst_(dst) {}
907 
908   template <class T, class V>
909   void Encode(T trait, V value) {
910     dst_->Set(trait, value);
911   }
912 
913   template <class T>
914   void Encode(T trait, const Slice& value) {
915     dst_->Set(trait, std::move(value.AsOwned()));
916   }
917 
918   void Encode(const Slice& key, const Slice& value) {
919     dst_->unknown_.Append(key.as_string_view(), value.Ref());
920   }
921 
922  private:
923   Output* dst_;
924 };
925 
926 // Callable for the ForEach in Encode() -- for each value, call the
927 // appropriate encoder method.
928 template <typename Encoder>
929 struct EncodeWrapper {
930   Encoder* encoder;
931   template <typename Which>
932   void operator()(const Value<Which>& which) {
933     which.EncodeTo(encoder);
934   }
935 };
936 
937 // Callable for the table ForEach in ForEach() -- for each value, call the
938 // appropriate visitor method.
939 template <typename Encoder>
940 struct ForEachWrapper {
941   Encoder* encoder;
942   template <typename Which>
943   void operator()(const Value<Which>& which) {
944     which.VisitWith(encoder);
945   }
946 };
947 
948 // Callable for the ForEach in Log()
949 struct LogWrapper {
950   LogFn log_fn;
951   template <typename Which>
952   void operator()(const Value<Which>& which) {
953     which.LogTo(log_fn);
954   }
955 };
956 
957 // Encoder to compute TransportSize
958 class TransportSizeEncoder {
959  public:
960   void Encode(const Slice& key, const Slice& value) {
961     size_ += key.length() + value.length() + 32;
962   }
963 
964   template <typename Which>
965   void Encode(Which, const typename Which::ValueType& value) {
966     Add(Which(), value);
967   }
968 
969   void Encode(ContentTypeMetadata,
970               const typename ContentTypeMetadata::ValueType& value) {
971     if (value == ContentTypeMetadata::kInvalid) return;
972     Add(ContentTypeMetadata(), value);
973   }
974 
975   size_t size() const { return size_; }
976 
977  private:
978   template <typename Which>
979   void Add(Which, const typename Which::ValueType& value) {
980     size_ += Which::key().length() + Which::Encode(value).length() + 32;
981   }
982 
983   uint32_t size_ = 0;
984 };
985 
986 // Handle unknown (non-trait-based) fields in the metadata map.
987 class UnknownMap {
988  public:
989   explicit UnknownMap(Arena* arena) : unknown_(arena) {}
990 
991   using BackingType = ChunkedVector<std::pair<Slice, Slice>, 10>;
992 
993   void Append(absl::string_view key, Slice value);
994   void Remove(absl::string_view key);
995   absl::optional<absl::string_view> GetStringValue(absl::string_view key,
996                                                    std::string* backing) const;
997 
998   BackingType::ConstForwardIterator begin() const { return unknown_.cbegin(); }
999   BackingType::ConstForwardIterator end() const { return unknown_.cend(); }
1000 
1001   bool empty() const { return unknown_.empty(); }
1002   size_t size() const { return unknown_.size(); }
1003   void Clear() { unknown_.Clear(); }
1004   Arena* arena() const { return unknown_.arena(); }
1005 
1006  private:
1007   // Backing store for added metadata.
1008   ChunkedVector<std::pair<Slice, Slice>, 10> unknown_;
1009 };
1010 
1011 // Given a factory template Factory, construct a type that derives from
1012 // Factory<MetadataTrait, MetadataTrait::CompressionTraits> for all
1013 // MetadataTraits. Useful for transports in defining the stateful parts of their
1014 // compression algorithm.
1015 template <template <typename, typename> class Factory,
1016           typename... MetadataTraits>
1017 struct StatefulCompressor;
1018 
1019 template <template <typename, typename> class Factory, typename MetadataTrait,
1020           bool kEncodable = IsEncodableTrait<MetadataTrait>::value>
1021 struct SpecificStatefulCompressor;
1022 
1023 template <template <typename, typename> class Factory, typename MetadataTrait>
1024 struct SpecificStatefulCompressor<Factory, MetadataTrait, true>
1025     : public Factory<MetadataTrait, typename MetadataTrait::CompressionTraits> {
1026 };
1027 
1028 template <template <typename, typename> class Factory, typename MetadataTrait>
1029 struct SpecificStatefulCompressor<Factory, MetadataTrait, false> {};
1030 
1031 template <template <typename, typename> class Factory, typename MetadataTrait,
1032           typename... MetadataTraits>
1033 struct StatefulCompressor<Factory, MetadataTrait, MetadataTraits...>
1034     : public SpecificStatefulCompressor<Factory, MetadataTrait>,
1035       public StatefulCompressor<Factory, MetadataTraits...> {};
1036 
1037 template <template <typename, typename> class Factory>
1038 struct StatefulCompressor<Factory> {};
1039 
1040 }  // namespace metadata_detail
1041 
1042 // Helper function for encoders
1043 // Given a metadata trait, convert the value to a slice.
1044 template <typename Which>
1045 absl::enable_if_t<std::is_same<typename Which::ValueType, Slice>::value,
1046                   const Slice&>
1047 MetadataValueAsSlice(const Slice& slice) {
1048   return slice;
1049 }
1050 
1051 template <typename Which>
1052 absl::enable_if_t<!std::is_same<typename Which::ValueType, Slice>::value, Slice>
1053 MetadataValueAsSlice(typename Which::ValueType value) {
1054   return Slice(Which::Encode(value));
1055 }
1056 
1057 // MetadataMap encodes the mapping of metadata keys to metadata values.
1058 //
1059 // MetadataMap takes a derived class and list of traits. Each of these trait
1060 // objects defines one metadata field that is used by core, and so should have
1061 // more specialized handling than just using the generic APIs.
1062 //
1063 // MetadataMap is the backing type for some derived type via the curiously
1064 // recursive template pattern. This is because many types consumed by
1065 // MetadataMap require the container type to operate on, and many of those
1066 // types are instantiated one per trait. A naive implementation without the
1067 // Derived type would, for traits A,B,C, then instantiate for some
1068 // T<Container, Trait>:
1069 //  - T<MetadataMap<A,B,C>, A>,
1070 //  - T<MetadataMap<A,B,C>, B>,
1071 //  - T<MetadataMap<A,B,C>, C>.
1072 // Since these types ultimately need to be recorded in the .dynstr segment
1073 // for dynamic linkers (if gRPC is linked as a static library) this would
1074 // create O(N^2) bytes of symbols even in stripped libraries. To avoid this
1075 // we use the derived type (e.g. grpc_metadata_batch right now) to capture
1076 // the container type, and we would write T<grpc_metadata_batch, A>, etc...
1077 // Note that now the container type uses a number of bytes that is independent
1078 // of the number of traits, and so we return to a linear symbol table growth
1079 // function.
1080 //
1081 // Each trait object has one of two possible signatures, depending on whether
1082 // that traits field is encodable or not.
1083 // Non-encodable traits are carried in a MetadataMap, but are never passed to
1084 // the application nor serialized to wire.
1085 //
1086 // Encodable traits have the following signature:
1087 // // Traits for the "grpc-xyz" metadata field:
1088 // struct GrpcXyzMetadata {
1089 //   // Can this metadata field be repeated?
1090 //   static constexpr bool kRepeatable = ...;
1091 //   // The type that's stored on MetadataBatch
1092 //   using ValueType = ...;
1093 //   // The type that's stored in compression/decompression tables
1094 //   using MementoType = ...;
1095 //   // The string key for this metadata type (for transports that require it)
1096 //   static absl::string_view key() { return "grpc-xyz"; }
1097 //   // Parse a memento from a slice
1098 //   // Takes ownership of value
1099 //   // Calls fn in the case of an error that should be reported to the user
1100 //   static MementoType ParseMemento(Slice value, MementoParseErrorFn fn) {
1101 //   ...
1102 //   }
1103 //   // Convert a memento to a value
1104 //   static ValueType MementoToValue(MementoType memento) { ... }
1105 //   // Convert a value to its canonical text wire format (the format that
1106 //   // ParseMemento will accept!)
1107 //   static Slice Encode(const ValueType& value);
1108 //   // Convert a value to something that can be passed to StrCat and
1109 //   displayed
1110 //   // for debugging
1111 //   static SomeStrCatableType DisplayValue(ValueType value) { ... }
1112 //   static SomeStrCatableType DisplayMemento(MementoType value) { ... }
1113 // };
1114 //
1115 // Non-encodable traits are determined by missing the key() method, and have
1116 // the following signature (and by convention omit the Metadata part of the
1117 // type name):
1118 // // Traits for the GrpcXyz field:
1119 // struct GrpcXyz {
1120 //   // The string key that should be used for debug dumps - should not be a
1121 //   // valid http2 key (ie all lower case)
1122 //   static absl::string_view DebugKey() { return "GRPC_XYZ"; }
1123 //   // Can this metadata field be repeated?
1124 //   static constexpr bool kRepeatable = ...;
1125 //   // The type that's stored on MetadataBatch
1126 //   using ValueType = ...;
1127 //   // Convert a value to something that can be passed to StrCat and
1128 //   displayed
1129 //   // for debugging
1130 //   static SomeStrCatableType DisplayValue(ValueType value) { ... }
1131 // };
1132 //
1133 // About parsing and mementos:
1134 //
1135 // Many gRPC transports exchange metadata as key/value strings, but also allow
1136 // for a more efficient representation as a single integer. We can use this
1137 // integer representation to avoid reparsing too, by storing the parsed value
1138 // in the compression table. This is what mementos are used for.
1139 //
1140 // A trait offers the capability to turn a slice into a memento via
1141 // ParseMemento. This is exposed to users of MetadataMap via the Parse()
1142 // method, that returns a ParsedMetadata object. That ParsedMetadata object
1143 // can in turn be used to set the same value on many different MetadataMaps
1144 // without having to reparse.
1145 //
1146 // Implementation wise, ParsedMetadata is a type erased wrapper around
1147 // MementoType. When we set a value on MetadataMap, we first turn that memento
1148 // into a value. For most types, this is going to be a no-op, but for example
1149 // for grpc-timeout we make the memento the timeout expressed on the wire, but
1150 // we make the value the timestamp of when the timeout will expire (i.e. the
1151 // deadline).
1152 template <class Derived, typename... Traits>
1153 class MetadataMap {
1154  public:
1155   explicit MetadataMap(Arena* arena);
1156   ~MetadataMap();
1157 
1158   // Given a compressor factory - template taking <MetadataTrait,
1159   // CompressionTrait>, StatefulCompressor<Factory> provides a type
1160   // derived from all Encodable traits in this MetadataMap.
1161   // This can be used by transports to delegate compression to the appropriate
1162   // compression algorithm.
1163   template <template <typename, typename> class Factory>
1164   using StatefulCompressor =
1165       metadata_detail::StatefulCompressor<Factory, Traits...>;
1166 
1167   MetadataMap(const MetadataMap&) = delete;
1168   MetadataMap& operator=(const MetadataMap&) = delete;
1169   MetadataMap(MetadataMap&&) noexcept;
1170   // We never create MetadataMap directly, instead we create Derived, but we
1171   // want to be able to move it without redeclaring this.
1172   // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1173   Derived& operator=(MetadataMap&&) noexcept;
1174 
1175   // Encode this metadata map into some encoder.
1176   // For each field that is set in the MetadataMap, call
1177   // encoder->Encode.
1178   //
1179   // For fields for which we have traits, this will be a method with
1180   // the signature:
1181   //    void Encode(TraitsType, typename TraitsType::ValueType value);
1182   // For fields for which we do not have traits, this will be a method
1183   // with the signature:
1184   //    void Encode(string_view key, Slice value);
1185   template <typename Encoder>
1186   void Encode(Encoder* encoder) const {
1187     table_.template ForEachIn<metadata_detail::EncodeWrapper<Encoder>,
1188                               Value<Traits>...>(
1189         metadata_detail::EncodeWrapper<Encoder>{encoder});
1190     for (const auto& unk : unknown_) {
1191       encoder->Encode(unk.first, unk.second);
1192     }
1193   }
1194 
1195   // Like Encode, but also visit the non-encodable fields.
1196   template <typename Encoder>
1197   void ForEach(Encoder* encoder) const {
1198     table_.ForEach(metadata_detail::ForEachWrapper<Encoder>{encoder});
1199     for (const auto& unk : unknown_) {
1200       encoder->Encode(unk.first, unk.second);
1201     }
1202   }
1203 
1204   // Similar to Encode, but targeted at logging: for each metadatum,
1205   // call f(key, value) as absl::string_views.
1206   void Log(metadata_detail::LogFn log_fn) const {
1207     table_.ForEach(metadata_detail::LogWrapper{log_fn});
1208     for (const auto& unk : unknown_) {
1209       log_fn(unk.first.as_string_view(), unk.second.as_string_view());
1210     }
1211   }
1212 
1213   std::string DebugString() const {
1214     metadata_detail::DebugStringBuilder builder;
1215     Log([&builder](absl::string_view key, absl::string_view value) {
1216       builder.Add(key, value);
1217     });
1218     return builder.TakeOutput();
1219   }
1220 
1221   // Get the pointer to the value of some known metadata.
1222   // Returns nullptr if the metadata is not present.
1223   // Causes a compilation error if Which is not an element of Traits.
1224   template <typename Which>
1225   const typename metadata_detail::Value<Which>::StorageType* get_pointer(
1226       Which) const {
1227     if (auto* p = table_.template get<Value<Which>>()) return &p->value;
1228     return nullptr;
1229   }
1230 
1231   // Get the pointer to the value of some known metadata.
1232   // Returns nullptr if the metadata is not present.
1233   // Causes a compilation error if Which is not an element of Traits.
1234   template <typename Which>
1235   typename metadata_detail::Value<Which>::StorageType* get_pointer(Which) {
1236     if (auto* p = table_.template get<Value<Which>>()) return &p->value;
1237     return nullptr;
1238   }
1239 
1240   // Get the pointer to the value of some known metadata.
1241   // Adds the default value for the metadata is not present.
1242   // Causes a compilation error if Which is not an element of Traits.
1243   template <typename Which>
1244   typename metadata_detail::Value<Which>::StorageType* GetOrCreatePointer(
1245       Which) {
1246     return &table_.template get_or_create<Value<Which>>()->value;
1247   }
1248 
1249   // Get the value of some known metadata.
1250   // Returns nullopt if the metadata is not present.
1251   // Causes a compilation error if Which is not an element of Traits.
1252   template <typename Which>
1253   absl::optional<typename Which::ValueType> get(Which) const {
1254     if (auto* p = table_.template get<Value<Which>>()) return p->value;
1255     return absl::nullopt;
1256   }
1257 
1258   // Set the value of some known metadata.
1259   // Returns a pointer to the new value.
1260   template <typename Which, typename... Args>
1261   absl::enable_if_t<Which::kRepeatable == false, void> Set(Which,
1262                                                            Args&&... args) {
1263     table_.template set<Value<Which>>(std::forward<Args>(args)...);
1264   }
1265   template <typename Which, typename... Args>
1266   absl::enable_if_t<Which::kRepeatable == true, void> Set(Which,
1267                                                           Args&&... args) {
1268     GetOrCreatePointer(Which())->emplace_back(std::forward<Args>(args)...);
1269   }
1270 
1271   // Remove a specific piece of known metadata.
1272   template <typename Which>
1273   void Remove(Which) {
1274     table_.template clear<Value<Which>>();
1275   }
1276 
1277   // Remove some metadata by name
1278   void Remove(absl::string_view key) {
1279     metadata_detail::RemoveHelper<Derived> helper(static_cast<Derived*>(this));
1280     metadata_detail::NameLookup<void, Traits...>::Lookup(key, &helper);
1281   }
1282 
1283   void Remove(const char* key) { Remove(absl::string_view(key)); }
1284 
1285   // Retrieve some metadata by name
1286   absl::optional<absl::string_view> GetStringValue(absl::string_view name,
1287                                                    std::string* buffer) const {
1288     metadata_detail::GetStringValueHelper<Derived> helper(
1289         static_cast<const Derived*>(this), buffer);
1290     return metadata_detail::NameLookup<void, Traits...>::Lookup(name, &helper);
1291   }
1292 
1293   // Extract a piece of known metadata.
1294   // Returns nullopt if the metadata was not present, or the value if it was.
1295   // The same as:
1296   //  auto value = m.get(T());
1297   //  m.Remove(T());
1298   template <typename Which>
1299   absl::enable_if_t<Which::kRepeatable == false,
1300                     absl::optional<typename Which::ValueType>>
1301   Take(Which which) {
1302     if (auto* p = get_pointer(which)) {
1303       absl::optional<typename Which::ValueType> value(std::move(*p));
1304       Remove(which);
1305       return value;
1306     }
1307     return {};
1308   }
1309 
1310   // Extract repeated known metadata.
1311   // Returns an empty vector if the metadata was not present.
1312   template <typename Which>
1313   absl::enable_if_t<Which::kRepeatable == true,
1314                     typename metadata_detail::Value<Which>::StorageType>
1315   Take(Which which) {
1316     if (auto* p = get_pointer(which)) {
1317       typename Value<Which>::StorageType value = std::move(*p);
1318       Remove(which);
1319       return value;
1320     }
1321     return {};
1322   }
1323 
1324   // Parse metadata from a key/value pair, and return an object representing
1325   // that result.
1326   static ParsedMetadata<Derived> Parse(absl::string_view key, Slice value,
1327                                        uint32_t transport_size,
1328                                        MetadataParseErrorFn on_error) {
1329     metadata_detail::ParseHelper<Derived> helper(value.TakeOwned(), on_error,
1330                                                  transport_size);
1331     return metadata_detail::NameLookup<void, Traits...>::Lookup(key, &helper);
1332   }
1333 
1334   // Set a value from a parsed metadata object.
1335   void Set(const ParsedMetadata<Derived>& m) {
1336     m.SetOnContainer(static_cast<Derived*>(this));
1337   }
1338 
1339   // Append a key/value pair - takes ownership of value
1340   void Append(absl::string_view key, Slice value,
1341               MetadataParseErrorFn on_error) {
1342     metadata_detail::AppendHelper<Derived> helper(static_cast<Derived*>(this),
1343                                                   value.TakeOwned(), on_error);
1344     metadata_detail::NameLookup<void, Traits...>::Lookup(key, &helper);
1345   }
1346 
1347   void Clear();
1348   size_t TransportSize() const;
1349   Derived Copy() const;
1350   bool empty() const { return table_.empty() && unknown_.empty(); }
1351   size_t count() const { return table_.count() + unknown_.size(); }
1352 
1353  private:
1354   friend class metadata_detail::AppendHelper<Derived>;
1355   friend class metadata_detail::GetStringValueHelper<Derived>;
1356   friend class metadata_detail::RemoveHelper<Derived>;
1357   friend class metadata_detail::CopySink<Derived>;
1358   friend class ParsedMetadata<Derived>;
1359 
1360   template <typename Which>
1361   using Value = metadata_detail::Value<Which>;
1362 
1363   // Table of known metadata types.
1364   PackedTable<Value<Traits>...> table_;
1365   metadata_detail::UnknownMap unknown_;
1366 };
1367 
1368 // Ok/not-ok check for metadata maps that contain GrpcStatusMetadata, so that
1369 // they can be used as result types for TrySeq.
1370 template <typename Derived, typename... Args>
1371 inline bool IsStatusOk(const MetadataMap<Derived, Args...>& m) {
1372   return m.get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
1373          GRPC_STATUS_OK;
1374 }
1375 
1376 template <typename Derived, typename... Traits>
1377 MetadataMap<Derived, Traits...>::MetadataMap(Arena* arena) : unknown_(arena) {}
1378 
1379 template <typename Derived, typename... Traits>
1380 MetadataMap<Derived, Traits...>::MetadataMap(MetadataMap&& other) noexcept
1381     : table_(std::move(other.table_)), unknown_(std::move(other.unknown_)) {}
1382 
1383 // We never create MetadataMap directly, instead we create Derived, but we
1384 // want to be able to move it without redeclaring this.
1385 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1386 template <typename Derived, typename... Traits>
1387 Derived& MetadataMap<Derived, Traits...>::operator=(
1388     MetadataMap&& other) noexcept {
1389   table_ = std::move(other.table_);
1390   unknown_ = std::move(other.unknown_);
1391   return static_cast<Derived&>(*this);
1392 }
1393 
1394 template <typename Derived, typename... Traits>
1395 MetadataMap<Derived, Traits...>::~MetadataMap() = default;
1396 
1397 template <typename Derived, typename... Traits>
1398 void MetadataMap<Derived, Traits...>::Clear() {
1399   table_.ClearAll();
1400   unknown_.Clear();
1401 }
1402 
1403 template <typename Derived, typename... Traits>
1404 size_t MetadataMap<Derived, Traits...>::TransportSize() const {
1405   metadata_detail::TransportSizeEncoder enc;
1406   Encode(&enc);
1407   return enc.size();
1408 }
1409 
1410 template <typename Derived, typename... Traits>
1411 Derived MetadataMap<Derived, Traits...>::Copy() const {
1412   Derived out(unknown_.arena());
1413   metadata_detail::CopySink<Derived> sink(&out);
1414   ForEach(&sink);
1415   return out;
1416 }
1417 
1418 }  // namespace grpc_core
1419 
1420 struct grpc_metadata_batch;
1421 
1422 using grpc_metadata_batch_base = grpc_core::MetadataMap<
1423     grpc_metadata_batch,
1424     // Colon prefixed headers first
1425     grpc_core::HttpPathMetadata, grpc_core::HttpAuthorityMetadata,
1426     grpc_core::HttpMethodMetadata, grpc_core::HttpStatusMetadata,
1427     grpc_core::HttpSchemeMetadata,
1428     // Non-colon prefixed headers begin here
1429     grpc_core::ContentTypeMetadata, grpc_core::TeMetadata,
1430     grpc_core::GrpcEncodingMetadata, grpc_core::GrpcInternalEncodingRequest,
1431     grpc_core::GrpcAcceptEncodingMetadata, grpc_core::GrpcStatusMetadata,
1432     grpc_core::GrpcTimeoutMetadata, grpc_core::GrpcPreviousRpcAttemptsMetadata,
1433     grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::UserAgentMetadata,
1434     grpc_core::GrpcMessageMetadata, grpc_core::HostMetadata,
1435     grpc_core::EndpointLoadMetricsBinMetadata,
1436     grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata,
1437     grpc_core::GrpcTagsBinMetadata, grpc_core::GrpcLbClientStatsMetadata,
1438     grpc_core::LbCostBinMetadata, grpc_core::LbTokenMetadata,
1439     // Non-encodable things
1440     grpc_core::GrpcStreamNetworkState, grpc_core::PeerString,
1441     grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire,
1442     grpc_core::GrpcCallWasCancelled, grpc_core::WaitForReady,
1443     grpc_core::GrpcTrailersOnly GRPC_CUSTOM_CLIENT_METADATA
1444         GRPC_CUSTOM_SERVER_METADATA>;
1445 
1446 struct grpc_metadata_batch : public grpc_metadata_batch_base {
1447   using grpc_metadata_batch_base::grpc_metadata_batch_base;
1448 };
1449 
1450 #endif  // GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
1451