• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/impl/compression_types.h>
23 #include <grpc/status.h>
24 #include <grpc/support/port_platform.h>
25 #include <stdlib.h>
26 
27 #include <cstdint>
28 #include <string>
29 #include <type_traits>
30 #include <utility>
31 
32 #include "absl/container/inlined_vector.h"
33 #include "absl/functional/function_ref.h"
34 #include "absl/log/check.h"
35 #include "absl/meta/type_traits.h"
36 #include "absl/strings/numbers.h"
37 #include "absl/strings/string_view.h"
38 #include "absl/types/optional.h"
39 #include "src/core/lib/compression/compression_internal.h"
40 #include "src/core/lib/experiments/experiments.h"
41 #include "src/core/lib/promise/poll.h"
42 #include "src/core/lib/slice/slice.h"
43 #include "src/core/lib/transport/custom_metadata.h"
44 #include "src/core/lib/transport/metadata_compression_traits.h"
45 #include "src/core/lib/transport/parsed_metadata.h"
46 #include "src/core/lib/transport/simple_slice_based_metadata.h"
47 #include "src/core/util/chunked_vector.h"
48 #include "src/core/util/if_list.h"
49 #include "src/core/util/packed_table.h"
50 #include "src/core/util/time.h"
51 #include "src/core/util/type_list.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   static constexpr bool kTransferOnTrailersOnly = false;
78   using ValueType = Timestamp;
79   using MementoType = Duration;
80   using CompressionTraits = TimeoutCompressor;
keyGrpcTimeoutMetadata81   static absl::string_view key() { return "grpc-timeout"; }
82   static MementoType ParseMemento(Slice value,
83                                   bool will_keep_past_request_lifetime,
84                                   MetadataParseErrorFn on_error);
85   static ValueType MementoToValue(MementoType timeout);
86   static Slice Encode(ValueType x);
DisplayValueGrpcTimeoutMetadata87   static std::string DisplayValue(ValueType x) { return x.ToString(); }
DisplayMementoGrpcTimeoutMetadata88   static std::string DisplayMemento(MementoType x) { return x.ToString(); }
89 };
90 
91 // TE metadata trait.
92 struct TeMetadata {
93   static constexpr bool kRepeatable = false;
94   static constexpr bool kTransferOnTrailersOnly = false;
95   // HTTP2 says that TE can either be empty or "trailers".
96   // Empty means this trait is not included, "trailers" means kTrailers, and
97   // kInvalid is used to remember an invalid value.
98   enum ValueType : uint8_t {
99     kTrailers,
100     kInvalid,
101   };
102   using MementoType = ValueType;
103   using CompressionTraits = KnownValueCompressor<ValueType, kTrailers>;
keyTeMetadata104   static absl::string_view key() { return "te"; }
105   static MementoType ParseMemento(Slice value,
106                                   bool will_keep_past_request_lifetime,
107                                   MetadataParseErrorFn on_error);
MementoToValueTeMetadata108   static ValueType MementoToValue(MementoType te) { return te; }
EncodeTeMetadata109   static StaticSlice Encode(ValueType x) {
110     CHECK(x == kTrailers);
111     return StaticSlice::FromStaticString("trailers");
112   }
113   static const char* DisplayValue(ValueType te);
DisplayMementoTeMetadata114   static const char* DisplayMemento(MementoType te) { return DisplayValue(te); }
115 };
116 
EncodedSizeOfKey(TeMetadata,TeMetadata::ValueType x)117 inline size_t EncodedSizeOfKey(TeMetadata, TeMetadata::ValueType x) {
118   return x == TeMetadata::kTrailers ? 8 : 0;
119 }
120 
121 // content-type metadata trait.
122 struct ContentTypeMetadata {
123   static constexpr bool kRepeatable = false;
124   static constexpr bool kTransferOnTrailersOnly = true;
125   // gRPC says that content-type can be application/grpc[;something]
126   // Core has only ever verified the prefix.
127   // IF we want to start verifying more, we can expand this type.
128   enum ValueType : uint8_t {
129     kApplicationGrpc,
130     kEmpty,
131     kInvalid,
132   };
133   using MementoType = ValueType;
134   using CompressionTraits = KnownValueCompressor<ValueType, kApplicationGrpc>;
keyContentTypeMetadata135   static absl::string_view key() { return "content-type"; }
136   static MementoType ParseMemento(Slice value,
137                                   bool will_keep_past_request_lifetime,
138                                   MetadataParseErrorFn on_error);
MementoToValueContentTypeMetadata139   static ValueType MementoToValue(MementoType content_type) {
140     return content_type;
141   }
142 
143   static StaticSlice Encode(ValueType x);
144   static const char* DisplayValue(ValueType content_type);
DisplayMementoContentTypeMetadata145   static const char* DisplayMemento(ValueType content_type) {
146     return DisplayValue(content_type);
147   }
148 };
149 
150 // scheme metadata trait.
151 struct HttpSchemeMetadata {
152   static constexpr bool kRepeatable = false;
153   static constexpr bool kTransferOnTrailersOnly = false;
154   enum ValueType : uint8_t {
155     kHttp,
156     kHttps,
157     kInvalid,
158   };
159   using MementoType = ValueType;
160   using CompressionTraits = HttpSchemeCompressor;
keyHttpSchemeMetadata161   static absl::string_view key() { return ":scheme"; }
ParseMementoHttpSchemeMetadata162   static MementoType ParseMemento(Slice value, bool,
163                                   MetadataParseErrorFn on_error) {
164     return Parse(value.as_string_view(), on_error);
165   }
166   static ValueType Parse(absl::string_view value,
167                          MetadataParseErrorFn on_error);
MementoToValueHttpSchemeMetadata168   static ValueType MementoToValue(MementoType content_type) {
169     return content_type;
170   }
171   static StaticSlice Encode(ValueType x);
172   static const char* DisplayValue(ValueType content_type);
DisplayMementoHttpSchemeMetadata173   static const char* DisplayMemento(MementoType content_type) {
174     return DisplayValue(content_type);
175   }
176 };
177 
178 size_t EncodedSizeOfKey(HttpSchemeMetadata, HttpSchemeMetadata::ValueType x);
179 
180 // method metadata trait.
181 struct HttpMethodMetadata {
182   static constexpr bool kRepeatable = false;
183   static constexpr bool kTransferOnTrailersOnly = false;
184   enum ValueType : uint8_t {
185     kPost,
186     kGet,
187     kPut,
188     kInvalid,
189   };
190   using MementoType = ValueType;
191   using CompressionTraits = HttpMethodCompressor;
keyHttpMethodMetadata192   static absl::string_view key() { return ":method"; }
193   static MementoType ParseMemento(Slice value,
194                                   bool will_keep_past_request_lifetime,
195                                   MetadataParseErrorFn on_error);
MementoToValueHttpMethodMetadata196   static ValueType MementoToValue(MementoType content_type) {
197     return content_type;
198   }
199   static StaticSlice Encode(ValueType x);
200   static const char* DisplayValue(ValueType content_type);
DisplayMementoHttpMethodMetadata201   static const char* DisplayMemento(MementoType content_type) {
202     return DisplayValue(content_type);
203   }
204 };
205 
206 // Base type for metadata pertaining to a single compression algorithm
207 // (e.g., "grpc-encoding").
208 struct CompressionAlgorithmBasedMetadata {
209   using ValueType = grpc_compression_algorithm;
210   using MementoType = ValueType;
211   static MementoType ParseMemento(Slice value,
212                                   bool will_keep_past_request_lifetime,
213                                   MetadataParseErrorFn on_error);
MementoToValueCompressionAlgorithmBasedMetadata214   static ValueType MementoToValue(MementoType x) { return x; }
EncodeCompressionAlgorithmBasedMetadata215   static Slice Encode(ValueType x) {
216     CHECK(x != GRPC_COMPRESS_ALGORITHMS_COUNT);
217     return Slice::FromStaticString(CompressionAlgorithmAsString(x));
218   }
DisplayValueCompressionAlgorithmBasedMetadata219   static const char* DisplayValue(ValueType x) {
220     if (const char* p = CompressionAlgorithmAsString(x)) {
221       return p;
222     } else {
223       return "<discarded-invalid-value>";
224     }
225   }
DisplayMementoCompressionAlgorithmBasedMetadata226   static const char* DisplayMemento(MementoType x) { return DisplayValue(x); }
227 };
228 
229 // grpc-encoding metadata trait.
230 struct GrpcEncodingMetadata : public CompressionAlgorithmBasedMetadata {
231   static constexpr bool kRepeatable = false;
232   static constexpr bool kTransferOnTrailersOnly = false;
233   using CompressionTraits =
234       SmallIntegralValuesCompressor<GRPC_COMPRESS_ALGORITHMS_COUNT>;
keyGrpcEncodingMetadata235   static absl::string_view key() { return "grpc-encoding"; }
236 };
237 
238 // grpc-internal-encoding-request metadata trait.
239 struct GrpcInternalEncodingRequest : public CompressionAlgorithmBasedMetadata {
240   static constexpr bool kRepeatable = false;
241   static constexpr bool kTransferOnTrailersOnly = false;
242   using CompressionTraits = NoCompressionCompressor;
keyGrpcInternalEncodingRequest243   static absl::string_view key() { return "grpc-internal-encoding-request"; }
244 };
245 
246 // grpc-accept-encoding metadata trait.
247 struct GrpcAcceptEncodingMetadata {
248   static constexpr bool kRepeatable = false;
249   static constexpr bool kTransferOnTrailersOnly = false;
keyGrpcAcceptEncodingMetadata250   static absl::string_view key() { return "grpc-accept-encoding"; }
251   using ValueType = CompressionAlgorithmSet;
252   using MementoType = ValueType;
253   using CompressionTraits = StableValueCompressor;
ParseMementoGrpcAcceptEncodingMetadata254   static MementoType ParseMemento(Slice value, bool, MetadataParseErrorFn) {
255     return CompressionAlgorithmSet::FromString(value.as_string_view());
256   }
MementoToValueGrpcAcceptEncodingMetadata257   static ValueType MementoToValue(MementoType x) { return x; }
EncodeGrpcAcceptEncodingMetadata258   static Slice Encode(ValueType x) { return x.ToSlice(); }
DisplayValueGrpcAcceptEncodingMetadata259   static absl::string_view DisplayValue(ValueType x) { return x.ToString(); }
DisplayMementoGrpcAcceptEncodingMetadata260   static absl::string_view DisplayMemento(MementoType x) {
261     return DisplayValue(x);
262   }
263 };
264 
265 // user-agent metadata trait.
266 struct UserAgentMetadata : public SimpleSliceBasedMetadata {
267   static constexpr bool kRepeatable = false;
268   static constexpr bool kTransferOnTrailersOnly = false;
269   using CompressionTraits = StableValueCompressor;
keyUserAgentMetadata270   static absl::string_view key() { return "user-agent"; }
271 };
272 
273 // grpc-message metadata trait.
274 struct GrpcMessageMetadata : public SimpleSliceBasedMetadata {
275   static constexpr bool kRepeatable = false;
276   static constexpr bool kTransferOnTrailersOnly = false;
277   using CompressionTraits = NoCompressionCompressor;
keyGrpcMessageMetadata278   static absl::string_view key() { return "grpc-message"; }
279 };
280 
281 // host metadata trait.
282 struct HostMetadata : public SimpleSliceBasedMetadata {
283   static constexpr bool kRepeatable = false;
284   static constexpr bool kTransferOnTrailersOnly = false;
285   using CompressionTraits = NoCompressionCompressor;
keyHostMetadata286   static absl::string_view key() { return "host"; }
287 };
288 
289 // endpoint-load-metrics-bin metadata trait.
290 struct EndpointLoadMetricsBinMetadata : public SimpleSliceBasedMetadata {
291   static constexpr bool kRepeatable = false;
292   static constexpr bool kTransferOnTrailersOnly = false;
293   using CompressionTraits = NoCompressionCompressor;
keyEndpointLoadMetricsBinMetadata294   static absl::string_view key() { return "endpoint-load-metrics-bin"; }
295 };
296 
297 // grpc-server-stats-bin metadata trait.
298 struct GrpcServerStatsBinMetadata : public SimpleSliceBasedMetadata {
299   static constexpr bool kRepeatable = false;
300   static constexpr bool kTransferOnTrailersOnly = false;
301   using CompressionTraits = NoCompressionCompressor;
keyGrpcServerStatsBinMetadata302   static absl::string_view key() { return "grpc-server-stats-bin"; }
303 };
304 
305 // grpc-trace-bin metadata trait.
306 struct GrpcTraceBinMetadata : public SimpleSliceBasedMetadata {
307   static constexpr bool kRepeatable = false;
308   static constexpr bool kTransferOnTrailersOnly = false;
309   using CompressionTraits = FrequentKeyWithNoValueCompressionCompressor;
keyGrpcTraceBinMetadata310   static absl::string_view key() { return "grpc-trace-bin"; }
311 };
312 
313 // grpc-tags-bin metadata trait.
314 struct GrpcTagsBinMetadata : public SimpleSliceBasedMetadata {
315   static constexpr bool kRepeatable = false;
316   static constexpr bool kTransferOnTrailersOnly = false;
317   using CompressionTraits = FrequentKeyWithNoValueCompressionCompressor;
keyGrpcTagsBinMetadata318   static absl::string_view key() { return "grpc-tags-bin"; }
319 };
320 
321 // XEnvoyPeerMetadata
322 struct XEnvoyPeerMetadata : public SimpleSliceBasedMetadata {
323   static constexpr bool kRepeatable = false;
324   static constexpr bool kTransferOnTrailersOnly = true;
325   using CompressionTraits = StableValueCompressor;
keyXEnvoyPeerMetadata326   static absl::string_view key() { return "x-envoy-peer-metadata"; }
327 };
328 
329 // :authority metadata trait.
330 struct HttpAuthorityMetadata : public SimpleSliceBasedMetadata {
331   static constexpr bool kRepeatable = false;
332   static constexpr bool kTransferOnTrailersOnly = false;
333   using CompressionTraits = SmallSetOfValuesCompressor;
keyHttpAuthorityMetadata334   static absl::string_view key() { return ":authority"; }
335 };
336 
337 // :path metadata trait.
338 struct HttpPathMetadata : public SimpleSliceBasedMetadata {
339   static constexpr bool kRepeatable = false;
340   static constexpr bool kTransferOnTrailersOnly = false;
341   using CompressionTraits = SmallSetOfValuesCompressor;
keyHttpPathMetadata342   static absl::string_view key() { return ":path"; }
343 };
344 
345 // We separate SimpleIntBasedMetadata into two pieces: one that does not
346 // depend on the invalid value, and one that does. This allows the compiler to
347 // easily see the functions that are shared, and helps reduce code bloat here.
348 template <typename Int>
349 struct SimpleIntBasedMetadataBase {
350   using ValueType = Int;
351   using MementoType = Int;
MementoToValueSimpleIntBasedMetadataBase352   static ValueType MementoToValue(MementoType value) { return value; }
EncodeSimpleIntBasedMetadataBase353   static Slice Encode(ValueType x) { return Slice::FromInt64(x); }
DisplayValueSimpleIntBasedMetadataBase354   static Int DisplayValue(ValueType x) { return x; }
DisplayMementoSimpleIntBasedMetadataBase355   static Int DisplayMemento(MementoType x) { return x; }
356 };
357 
358 template <typename Int, Int kInvalidValue>
359 struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> {
invalid_valueSimpleIntBasedMetadata360   static constexpr Int invalid_value() { return kInvalidValue; }
ParseMementoSimpleIntBasedMetadata361   static Int ParseMemento(Slice value, bool, MetadataParseErrorFn on_error) {
362     Int out;
363     if (!absl::SimpleAtoi(value.as_string_view(), &out)) {
364       on_error("not an integer", value);
365       out = kInvalidValue;
366     }
367     return out;
368   }
369 };
370 
371 // grpc-status metadata trait.
372 struct GrpcStatusMetadata
373     : public SimpleIntBasedMetadata<grpc_status_code, GRPC_STATUS_UNKNOWN> {
374   static constexpr bool kRepeatable = false;
375   static constexpr bool kTransferOnTrailersOnly = false;
376   using CompressionTraits = SmallIntegralValuesCompressor<16>;
keyGrpcStatusMetadata377   static absl::string_view key() { return "grpc-status"; }
378 };
379 
380 // grpc-previous-rpc-attempts metadata trait.
381 struct GrpcPreviousRpcAttemptsMetadata
382     : public SimpleIntBasedMetadata<uint32_t, 0> {
383   static constexpr bool kRepeatable = false;
384   static constexpr bool kTransferOnTrailersOnly = false;
385   using CompressionTraits = NoCompressionCompressor;
keyGrpcPreviousRpcAttemptsMetadata386   static absl::string_view key() { return "grpc-previous-rpc-attempts"; }
387 };
388 
389 // grpc-retry-pushback-ms metadata trait.
390 struct GrpcRetryPushbackMsMetadata {
391   static constexpr bool kRepeatable = false;
392   static constexpr bool kTransferOnTrailersOnly = false;
keyGrpcRetryPushbackMsMetadata393   static absl::string_view key() { return "grpc-retry-pushback-ms"; }
394   using ValueType = Duration;
395   using MementoType = Duration;
396   using CompressionTraits = NoCompressionCompressor;
MementoToValueGrpcRetryPushbackMsMetadata397   static ValueType MementoToValue(MementoType x) { return x; }
EncodeGrpcRetryPushbackMsMetadata398   static Slice Encode(Duration x) { return Slice::FromInt64(x.millis()); }
DisplayValueGrpcRetryPushbackMsMetadata399   static int64_t DisplayValue(Duration x) { return x.millis(); }
DisplayMementoGrpcRetryPushbackMsMetadata400   static int64_t DisplayMemento(Duration x) { return DisplayValue(x); }
401   static Duration ParseMemento(Slice value,
402                                bool will_keep_past_request_lifetime,
403                                MetadataParseErrorFn on_error);
404 };
405 
406 // :status metadata trait.
407 // TODO(ctiller): consider moving to uint16_t
408 struct HttpStatusMetadata : public SimpleIntBasedMetadata<uint32_t, 0> {
409   static constexpr bool kRepeatable = false;
410   static constexpr bool kTransferOnTrailersOnly = true;
411   using CompressionTraits = HttpStatusCompressor;
keyHttpStatusMetadata412   static absl::string_view key() { return ":status"; }
413 };
414 
415 // "secret" metadata trait used to pass load balancing token between filters.
416 // This should not be exposed outside of gRPC core.
417 class GrpcLbClientStats;
418 
419 struct GrpcLbClientStatsMetadata {
420   static constexpr bool kRepeatable = false;
421   static constexpr bool kTransferOnTrailersOnly = false;
keyGrpcLbClientStatsMetadata422   static absl::string_view key() { return "grpclb_client_stats"; }
423   using ValueType = GrpcLbClientStats*;
424   using MementoType = ValueType;
425   using CompressionTraits = NoCompressionCompressor;
MementoToValueGrpcLbClientStatsMetadata426   static ValueType MementoToValue(MementoType value) { return value; }
EncodeGrpcLbClientStatsMetadata427   static Slice Encode(ValueType) { abort(); }
DisplayValueGrpcLbClientStatsMetadata428   static const char* DisplayValue(ValueType) { return "<internal-lb-stats>"; }
DisplayMementoGrpcLbClientStatsMetadata429   static const char* DisplayMemento(MementoType) {
430     return "<internal-lb-stats>";
431   }
ParseMementoGrpcLbClientStatsMetadata432   static MementoType ParseMemento(Slice, bool, MetadataParseErrorFn error) {
433     error("not a valid value for grpclb_client_stats", Slice());
434     return nullptr;
435   }
436 };
437 
EncodedSizeOfKey(GrpcLbClientStatsMetadata,GrpcLbClientStatsMetadata::ValueType)438 inline size_t EncodedSizeOfKey(GrpcLbClientStatsMetadata,
439                                GrpcLbClientStatsMetadata::ValueType) {
440   return 0;
441 }
442 
443 // lb-token metadata
444 struct LbTokenMetadata : public SimpleSliceBasedMetadata {
445   static constexpr bool kRepeatable = false;
446   static constexpr bool kTransferOnTrailersOnly = false;
447   using CompressionTraits = NoCompressionCompressor;
keyLbTokenMetadata448   static absl::string_view key() { return "lb-token"; }
449 };
450 
451 // lb-cost-bin metadata
452 struct LbCostBinMetadata {
453   static constexpr bool kRepeatable = true;
454   static constexpr bool kTransferOnTrailersOnly = false;
keyLbCostBinMetadata455   static absl::string_view key() { return "lb-cost-bin"; }
456   struct ValueType {
457     double cost;
458     std::string name;
459   };
460   using MementoType = ValueType;
461   using CompressionTraits = NoCompressionCompressor;
MementoToValueLbCostBinMetadata462   static ValueType MementoToValue(MementoType value) { return value; }
463   static Slice Encode(const ValueType& x);
464   static std::string DisplayValue(ValueType x);
DisplayMementoLbCostBinMetadata465   static std::string DisplayMemento(MementoType x) { return DisplayValue(x); }
466   static MementoType ParseMemento(Slice value,
467                                   bool will_keep_past_request_lifetime,
468                                   MetadataParseErrorFn on_error);
469 };
470 
471 // traceparent metadata
472 struct W3CTraceParentMetadata : public SimpleSliceBasedMetadata {
473   static constexpr bool kRepeatable = false;
474   static constexpr bool kTransferOnTrailersOnly = false;
475   using CompressionTraits = NoCompressionCompressor;
keyW3CTraceParentMetadata476   static absl::string_view key() { return "traceparent"; }
477 };
478 
479 // Annotation added by a transport to note whether a failed request was never
480 // placed on the wire, or never seen by a server.
481 struct GrpcStreamNetworkState {
DebugKeyGrpcStreamNetworkState482   static absl::string_view DebugKey() { return "GrpcStreamNetworkState"; }
483   static constexpr bool kRepeatable = false;
484   static constexpr bool kTransferOnTrailersOnly = false;
485   enum ValueType : uint8_t {
486     kNotSentOnWire,
487     kNotSeenByServer,
488   };
489   static std::string DisplayValue(ValueType x);
490 };
491 
492 // Annotation added by a server transport to note the peer making a request.
493 struct PeerString {
DebugKeyPeerString494   static absl::string_view DebugKey() { return "PeerString"; }
495   static constexpr bool kRepeatable = false;
496   using ValueType = Slice;
497   static std::string DisplayValue(const ValueType& x);
498 };
499 
500 // Annotation added by various systems to describe the reason for a failure.
501 struct GrpcStatusContext {
DebugKeyGrpcStatusContext502   static absl::string_view DebugKey() { return "GrpcStatusContext"; }
503   static constexpr bool kRepeatable = true;
504   using ValueType = std::string;
505   static const std::string& DisplayValue(const std::string& x);
506 };
507 
508 // Annotation added by a transport to note that the status came from the wire.
509 struct GrpcStatusFromWire {
DebugKeyGrpcStatusFromWire510   static absl::string_view DebugKey() { return "GrpcStatusFromWire"; }
511   static constexpr bool kRepeatable = false;
512   using ValueType = bool;
DisplayValueGrpcStatusFromWire513   static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
514 };
515 
516 // Annotation to denote that this call qualifies for cancelled=1 for the
517 // RECV_CLOSE_ON_SERVER op
518 struct GrpcCallWasCancelled {
DebugKeyGrpcCallWasCancelled519   static absl::string_view DebugKey() { return "GrpcCallWasCancelled"; }
520   static constexpr bool kRepeatable = false;
521   using ValueType = bool;
DisplayValueGrpcCallWasCancelled522   static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
523 };
524 
525 // Annotation added by client surface code to denote wait-for-ready state
526 struct WaitForReady {
527   struct ValueType {
528     bool value = false;
529     bool explicitly_set = false;
530   };
DebugKeyWaitForReady531   static absl::string_view DebugKey() { return "WaitForReady"; }
532   static constexpr bool kRepeatable = false;
533   static std::string DisplayValue(ValueType x);
534 };
535 
536 // Annotation added by retry code to indicate a transparent retry.
537 struct IsTransparentRetry {
DebugKeyIsTransparentRetry538   static absl::string_view DebugKey() { return "IsTransparentRetry"; }
539   static constexpr bool kRepeatable = false;
540   using ValueType = bool;
DisplayValueIsTransparentRetry541   static std::string DisplayValue(ValueType x) { return x ? "true" : "false"; }
542 };
543 
544 // Annotation added by a transport to note that server trailing metadata
545 // is a Trailers-Only response.
546 struct GrpcTrailersOnly {
DebugKeyGrpcTrailersOnly547   static absl::string_view DebugKey() { return "GrpcTrailersOnly"; }
548   static constexpr bool kRepeatable = false;
549   using ValueType = bool;
DisplayValueGrpcTrailersOnly550   static absl::string_view DisplayValue(bool x) { return x ? "true" : "false"; }
551 };
552 
553 // On the client-side, the value is a uintptr_t with a value of 1 if the call
554 // has a registered/known method, or 0, if it's not known. On the server side,
555 // the value is a (ChannelRegisteredMethod*).
556 struct GrpcRegisteredMethod {
DebugKeyGrpcRegisteredMethod557   static absl::string_view DebugKey() { return "GrpcRegisteredMethod"; }
558   static constexpr bool kRepeatable = false;
559   using ValueType = void*;
560   static std::string DisplayValue(void* x);
561 };
562 
563 // Annotation added by filters to inform the transport to tarpit this
564 // response: add some random delay to thwart certain kinds of attacks.
565 struct GrpcTarPit {
DebugKeyGrpcTarPit566   static absl::string_view DebugKey() { return "GrpcTarPit"; }
567   static constexpr bool kRepeatable = false;
568   using ValueType = Empty;
DisplayValueGrpcTarPit569   static absl::string_view DisplayValue(Empty) { return "tarpit"; }
570 };
571 
572 namespace metadata_detail {
573 
574 // Build a key/value formatted debug string.
575 // Output looks like 'key1: value1, key2: value2'
576 // The string is expected to be readable, but not necessarily parsable.
577 class DebugStringBuilder {
578  public:
579   // Add one key/value pair to the output if it is allow listed.
580   // Redact only the value if it is not allow listed.
581   void AddAfterRedaction(absl::string_view key, absl::string_view value);
582 
583   // Finalize the output and return the string.
584   // Subsequent Add calls are UB.
TakeOutput()585   std::string TakeOutput() { return std::move(out_); }
586 
587  private:
588   bool IsAllowListed(absl::string_view key) const;
589   void Add(absl::string_view key, absl::string_view value);
590   std::string out_;
591 };
592 
593 // IsEncodable: Given a trait, determine if that trait is encodable, or is
594 // just a value attached to a MetadataMap. We use the presence of the key()
595 // static method to determine if a trait is encodable or not - encodable
596 // traits have string names, and non-encodable traits do not.
597 template <typename Trait, typename Ignored = void>
598 struct IsEncodableTrait {
599   static const bool value = false;
600 };
601 
602 template <typename Trait>
603 struct IsEncodableTrait<Trait, absl::void_t<decltype(Trait::key())>> {
604   static const bool value = true;
605 };
606 
607 template <typename MustBeVoid, typename... Traits>
608 struct EncodableTraits;
609 
610 template <typename Trait, typename... Traits>
611 struct EncodableTraits<absl::enable_if_t<IsEncodableTrait<Trait>::value, void>,
612                        Trait, Traits...> {
613   using List =
614       typename EncodableTraits<void,
615                                Traits...>::List::template PushFront<Trait>;
616 };
617 
618 template <typename Trait, typename... Traits>
619 struct EncodableTraits<absl::enable_if_t<!IsEncodableTrait<Trait>::value, void>,
620                        Trait, Traits...> {
621   using List = typename EncodableTraits<void, Traits...>::List;
622 };
623 
624 template <>
625 struct EncodableTraits<void> {
626   using List = Typelist<>;
627 };
628 
629 template <typename Trait>
630 struct EncodableNameLookupKeyComparison {
631   bool operator()(absl::string_view key) { return key == Trait::key(); }
632 };
633 
634 template <typename Trait, typename Op>
635 struct EncodableNameLookupOnFound {
636   auto operator()(Op* op) { return op->Found(Trait()); }
637 };
638 
639 template <typename... Traits>
640 struct EncodableNameLookup {
641   template <typename Op>
642   static auto Lookup(absl::string_view key, Op* op) {
643     return IfList(
644         key, op, [key](Op* op) { return op->NotFound(key); },
645         EncodableNameLookupKeyComparison<Traits>()...,
646         EncodableNameLookupOnFound<Traits, Op>()...);
647   }
648 };
649 
650 template <typename... Traits>
651 using NameLookup = typename EncodableTraits<
652     void, Traits...>::List::template Instantiate<EncodableNameLookup>;
653 
654 // Helper to take a slice to a memento to a value.
655 // By splitting this part out we can scale code size as the number of
656 // (memento, value) types, rather than as the number of traits.
657 template <typename ParseMementoFn, typename MementoToValueFn>
658 struct ParseValue {
659   template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value>
660   static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value,
661                                            MetadataParseErrorFn on_error)
662       -> decltype(memento_to_value(parse_memento(std::move(*value), false,
663                                                  on_error))) {
664     return memento_to_value(parse_memento(std::move(*value), false, on_error));
665   }
666 };
667 
668 // This is an "Op" type for NameLookup.
669 // Used for MetadataMap::Parse, its Found/NotFound methods turn a slice into a
670 // ParsedMetadata object.
671 template <typename Container>
672 class ParseHelper {
673  public:
674   ParseHelper(Slice value, bool will_keep_past_request_lifetime,
675               MetadataParseErrorFn on_error, size_t transport_size)
676       : value_(std::move(value)),
677         will_keep_past_request_lifetime_(will_keep_past_request_lifetime),
678         on_error_(on_error),
679         transport_size_(transport_size) {}
680 
681   template <typename Trait>
682   GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) {
683     return ParsedMetadata<Container>(
684         trait,
685         ParseValueToMemento<typename Trait::MementoType, Trait::ParseMemento>(),
686         static_cast<uint32_t>(transport_size_));
687   }
688 
689   GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> NotFound(
690       absl::string_view key) {
691     return ParsedMetadata<Container>(
692         typename ParsedMetadata<Container>::FromSlicePair{},
693         Slice::FromCopiedString(key),
694         will_keep_past_request_lifetime_ ? value_.TakeUniquelyOwned()
695                                          : std::move(value_),
696         transport_size_);
697   }
698 
699  private:
700   template <typename T, T (*parse_memento)(Slice, bool, MetadataParseErrorFn)>
701   GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() {
702     return parse_memento(std::move(value_), will_keep_past_request_lifetime_,
703                          on_error_);
704   }
705 
706   Slice value_;
707   const bool will_keep_past_request_lifetime_;
708   MetadataParseErrorFn on_error_;
709   const size_t transport_size_;
710 };
711 
712 // This is an "Op" type for NameLookup.
713 // Used for MetadataMap::Append, its Found/NotFound methods turn a slice into
714 // a value and add it to a container.
715 template <typename Container>
716 class AppendHelper {
717  public:
718   AppendHelper(Container* container, Slice value, MetadataParseErrorFn on_error)
719       : container_(container), value_(std::move(value)), on_error_(on_error) {}
720 
721   template <typename Trait>
722   GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
723     container_->Set(
724         trait, ParseValue<decltype(Trait::ParseMemento),
725                           decltype(Trait::MementoToValue)>::
726                    template Parse<Trait::ParseMemento, Trait::MementoToValue>(
727                        &value_, on_error_));
728   }
729 
730   GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
731     container_->unknown_.Append(key, std::move(value_));
732   }
733 
734  private:
735   Container* const container_;
736   Slice value_;
737   MetadataParseErrorFn on_error_;
738 };
739 
740 // This is an "Op" type for NameLookup.
741 // Used for MetadataMap::Remove, its Found/NotFound methods remove a key from
742 // the container.
743 template <typename Container>
744 class RemoveHelper {
745  public:
746   explicit RemoveHelper(Container* container) : container_(container) {}
747 
748   template <typename Trait>
749   GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) {
750     container_->Remove(trait);
751   }
752 
753   GPR_ATTRIBUTE_NOINLINE void NotFound(absl::string_view key) {
754     container_->unknown_.Remove(key);
755   }
756 
757  private:
758   Container* const container_;
759 };
760 
761 // This is an "Op" type for NameLookup.
762 // Used for MetadataMap::GetStringValue, its Found/NotFound methods generated
763 // a string value from the container.
764 template <typename Container>
765 class GetStringValueHelper {
766  public:
767   explicit GetStringValueHelper(const Container* container,
768                                 std::string* backing)
769       : container_(container), backing_(backing) {}
770 
771   template <typename Trait>
772   GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
773       Trait::kRepeatable == false &&
774           std::is_same<Slice, typename Trait::ValueType>::value,
775       absl::optional<absl::string_view>>
776   Found(Trait) {
777     const auto* value = container_->get_pointer(Trait());
778     if (value == nullptr) return absl::nullopt;
779     return value->as_string_view();
780   }
781 
782   template <typename Trait>
783   GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
784       Trait::kRepeatable == true &&
785           !std::is_same<Slice, typename Trait::ValueType>::value,
786       absl::optional<absl::string_view>>
787   Found(Trait) {
788     const auto* value = container_->get_pointer(Trait());
789     if (value == nullptr) return absl::nullopt;
790     backing_->clear();
791     for (const auto& v : *value) {
792       if (!backing_->empty()) backing_->push_back(',');
793       auto new_segment = Trait::Encode(v);
794       backing_->append(new_segment.begin(), new_segment.end());
795     }
796     return *backing_;
797   }
798 
799   template <typename Trait>
800   GPR_ATTRIBUTE_NOINLINE absl::enable_if_t<
801       Trait::kRepeatable == false &&
802           !std::is_same<Slice, typename Trait::ValueType>::value,
803       absl::optional<absl::string_view>>
804   Found(Trait) {
805     const auto* value = container_->get_pointer(Trait());
806     if (value == nullptr) return absl::nullopt;
807     *backing_ = std::string(Trait::Encode(*value).as_string_view());
808     return *backing_;
809   }
810 
811   GPR_ATTRIBUTE_NOINLINE absl::optional<absl::string_view> NotFound(
812       absl::string_view key) {
813     return container_->unknown_.GetStringValue(key, backing_);
814   }
815 
816  private:
817   const Container* const container_;
818   std::string* backing_;
819 };
820 
821 // Sink for key value logs
822 using LogFn = absl::FunctionRef<void(absl::string_view, absl::string_view)>;
823 
824 template <typename T>
825 struct AdaptDisplayValueToLog {
826   static std::string ToString(const T& value) { return std::to_string(value); }
827 };
828 
829 template <>
830 struct AdaptDisplayValueToLog<std::string> {
831   static std::string ToString(const std::string& value) { return value; }
832 };
833 
834 template <>
835 struct AdaptDisplayValueToLog<const std::string&> {
836   static std::string ToString(const std::string& value) { return value; }
837 };
838 
839 template <>
840 struct AdaptDisplayValueToLog<absl::string_view> {
841   static std::string ToString(absl::string_view value) {
842     return std::string(value);
843   }
844 };
845 
846 template <>
847 struct AdaptDisplayValueToLog<Slice> {
848   static std::string ToString(Slice value) {
849     return std::string(value.as_string_view());
850   }
851 };
852 
853 template <>
854 struct AdaptDisplayValueToLog<const char*> {
855   static std::string ToString(const char* value) { return std::string(value); }
856 };
857 
858 template <>
859 struct AdaptDisplayValueToLog<StaticSlice> {
860   static absl::string_view ToString(StaticSlice value) {
861     return value.as_string_view();
862   }
863 };
864 
865 template <typename T, typename U, typename V>
866 GPR_ATTRIBUTE_NOINLINE void LogKeyValueTo(absl::string_view key, const T& value,
867                                           V (*display_value)(U), LogFn log_fn) {
868   log_fn(key, AdaptDisplayValueToLog<V>::ToString(display_value(value)));
869 }
870 
871 // Generate a strong type for metadata values per trait.
872 template <typename Which, typename Ignored = void>
873 struct Value;
874 
875 template <typename Which>
876 struct Value<Which, absl::enable_if_t<Which::kRepeatable == false &&
877                                           IsEncodableTrait<Which>::value,
878                                       void>> {
879   Value() = default;
880   explicit Value(const typename Which::ValueType& value) : value(value) {}
881   explicit Value(typename Which::ValueType&& value)
882       : value(std::forward<typename Which::ValueType>(value)) {}
883   Value(const Value&) = delete;
884   Value& operator=(const Value&) = delete;
885   Value(Value&&) noexcept = default;
886   Value& operator=(Value&& other) noexcept {
887     value = std::move(other.value);
888     return *this;
889   }
890   template <typename Encoder>
891   void EncodeTo(Encoder* encoder) const {
892     encoder->Encode(Which(), value);
893   }
894   template <typename Encoder>
895   void VisitWith(Encoder* encoder) const {
896     return EncodeTo(encoder);
897   }
898   void LogTo(LogFn log_fn) const {
899     LogKeyValueTo(Which::key(), value, Which::DisplayValue, log_fn);
900   }
901   using StorageType = typename Which::ValueType;
902   GPR_NO_UNIQUE_ADDRESS StorageType value;
903 };
904 
905 template <typename Which>
906 struct Value<Which, absl::enable_if_t<Which::kRepeatable == false &&
907                                           !IsEncodableTrait<Which>::value,
908                                       void>> {
909   Value() = default;
910   explicit Value(const typename Which::ValueType& value) : value(value) {}
911   explicit Value(typename Which::ValueType&& value)
912       : value(std::forward<typename Which::ValueType>(value)) {}
913   Value(const Value&) = delete;
914   Value& operator=(const Value&) = delete;
915   Value(Value&&) noexcept = default;
916   Value& operator=(Value&& other) noexcept {
917     value = std::move(other.value);
918     return *this;
919   }
920   template <typename Encoder>
921   void EncodeTo(Encoder*) const {}
922   template <typename Encoder>
923   void VisitWith(Encoder* encoder) const {
924     encoder->Encode(Which(), value);
925   }
926   void LogTo(LogFn log_fn) const {
927     LogKeyValueTo(Which::DebugKey(), value, Which::DisplayValue, log_fn);
928   }
929   using StorageType = typename Which::ValueType;
930   GPR_NO_UNIQUE_ADDRESS StorageType value;
931 };
932 
933 template <typename Which>
934 struct Value<Which, absl::enable_if_t<Which::kRepeatable == true &&
935                                           IsEncodableTrait<Which>::value,
936                                       void>> {
937   Value() = default;
938   explicit Value(const typename Which::ValueType& value) {
939     this->value.push_back(value);
940   }
941   explicit Value(typename Which::ValueType&& value) {
942     this->value.emplace_back(std::forward<typename Which::ValueType>(value));
943   }
944   Value(const Value&) = delete;
945   Value& operator=(const Value&) = delete;
946   Value(Value&& other) noexcept : value(std::move(other.value)) {}
947   Value& operator=(Value&& other) noexcept {
948     value = std::move(other.value);
949     return *this;
950   }
951   template <typename Encoder>
952   void EncodeTo(Encoder* encoder) const {
953     for (const auto& v : value) {
954       encoder->Encode(Which(), v);
955     }
956   }
957   template <typename Encoder>
958   void VisitWith(Encoder* encoder) const {
959     return EncodeTo(encoder);
960   }
961   void LogTo(LogFn log_fn) const {
962     for (const auto& v : value) {
963       LogKeyValueTo(Which::key(), v, Which::Encode, log_fn);
964     }
965   }
966   using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
967   StorageType value;
968 };
969 
970 template <typename Which>
971 struct Value<Which, absl::enable_if_t<Which::kRepeatable == true &&
972                                           !IsEncodableTrait<Which>::value,
973                                       void>> {
974   Value() = default;
975   explicit Value(const typename Which::ValueType& value) {
976     this->value.push_back(value);
977   }
978   explicit Value(typename Which::ValueType&& value) {
979     this->value.emplace_back(std::forward<typename Which::ValueType>(value));
980   }
981   Value(const Value&) = delete;
982   Value& operator=(const Value&) = delete;
983   Value(Value&& other) noexcept : value(std::move(other.value)) {}
984   Value& operator=(Value&& other) noexcept {
985     value = std::move(other.value);
986     return *this;
987   }
988   template <typename Encoder>
989   void EncodeTo(Encoder*) const {}
990   template <typename Encoder>
991   void VisitWith(Encoder* encoder) const {
992     for (const auto& v : value) {
993       encoder->Encode(Which(), v);
994     }
995   }
996   void LogTo(LogFn log_fn) const {
997     for (const auto& v : value) {
998       LogKeyValueTo(Which::DebugKey(), v, Which::DisplayValue, log_fn);
999     }
1000   }
1001   using StorageType = absl::InlinedVector<typename Which::ValueType, 1>;
1002   StorageType value;
1003 };
1004 
1005 // Encoder to copy some metadata
1006 template <typename Output>
1007 class CopySink {
1008  public:
1009   explicit CopySink(Output* dst) : dst_(dst) {}
1010 
1011   template <class T, class V>
1012   void Encode(T trait, V value) {
1013     dst_->Set(trait, value);
1014   }
1015 
1016   template <class T>
1017   void Encode(T trait, const Slice& value) {
1018     dst_->Set(trait, std::move(value.AsOwned()));
1019   }
1020 
1021   void Encode(const Slice& key, const Slice& value) {
1022     dst_->unknown_.Append(key.as_string_view(), value.Ref());
1023   }
1024 
1025  private:
1026   Output* dst_;
1027 };
1028 
1029 // Callable for the ForEach in Encode() -- for each value, call the
1030 // appropriate encoder method.
1031 template <typename Encoder>
1032 struct EncodeWrapper {
1033   Encoder* encoder;
1034   template <typename Which>
1035   void operator()(const Value<Which>& which) {
1036     which.EncodeTo(encoder);
1037   }
1038 };
1039 
1040 // Callable for the table ForEach in ForEach() -- for each value, call the
1041 // appropriate visitor method.
1042 template <typename Encoder>
1043 struct ForEachWrapper {
1044   Encoder* encoder;
1045   template <typename Which>
1046   void operator()(const Value<Which>& which) {
1047     which.VisitWith(encoder);
1048   }
1049 };
1050 
1051 // Callable for the ForEach in Log()
1052 struct LogWrapper {
1053   LogFn log_fn;
1054   template <typename Which>
1055   void operator()(const Value<Which>& which) {
1056     which.LogTo(log_fn);
1057   }
1058 };
1059 
1060 // Callable for the table FilterIn -- for each value, call the
1061 // appropriate filter method to determine of the value should be kept or
1062 // removed.
1063 template <typename Filterer>
1064 struct FilterWrapper {
1065   Filterer filter_fn;
1066 
1067   template <typename Which,
1068             absl::enable_if_t<IsEncodableTrait<Which>::value, bool> = true>
1069   bool operator()(const Value<Which>& /*which*/) {
1070     return filter_fn(Which());
1071   }
1072 
1073   template <typename Which,
1074             absl::enable_if_t<!IsEncodableTrait<Which>::value, bool> = true>
1075   bool operator()(const Value<Which>& /*which*/) {
1076     return true;
1077   }
1078 };
1079 
1080 // Encoder to compute TransportSize
1081 class TransportSizeEncoder {
1082  public:
1083   void Encode(const Slice& key, const Slice& value) {
1084     size_ += key.length() + value.length() + 32;
1085   }
1086 
1087   template <typename Which>
1088   void Encode(Which, const typename Which::ValueType& value) {
1089     Add(Which(), value);
1090   }
1091 
1092   void Encode(ContentTypeMetadata,
1093               const typename ContentTypeMetadata::ValueType& value) {
1094     if (value == ContentTypeMetadata::kInvalid) return;
1095     Add(ContentTypeMetadata(), value);
1096   }
1097 
1098   size_t size() const { return size_; }
1099 
1100  private:
1101   template <typename Which>
1102   void Add(Which, const typename Which::ValueType& value) {
1103     size_ += Which::key().length() + Which::Encode(value).length() + 32;
1104   }
1105 
1106   uint32_t size_ = 0;
1107 };
1108 
1109 // Handle unknown (non-trait-based) fields in the metadata map.
1110 class UnknownMap {
1111  public:
1112   using BackingType = std::vector<std::pair<Slice, Slice>>;
1113 
1114   void Append(absl::string_view key, Slice value);
1115   void Remove(absl::string_view key);
1116   absl::optional<absl::string_view> GetStringValue(absl::string_view key,
1117                                                    std::string* backing) const;
1118 
1119   BackingType::const_iterator begin() const { return unknown_.cbegin(); }
1120   BackingType::const_iterator end() const { return unknown_.cend(); }
1121 
1122   template <typename Filterer>
1123   void Filter(Filterer* filter_fn) {
1124     unknown_.erase(
1125         std::remove_if(unknown_.begin(), unknown_.end(),
1126                        [&](auto& pair) {
1127                          return !(*filter_fn)(pair.first.as_string_view());
1128                        }),
1129         unknown_.end());
1130   }
1131 
1132   bool empty() const { return unknown_.empty(); }
1133   size_t size() const { return unknown_.size(); }
1134   void Clear() { unknown_.clear(); }
1135 
1136  private:
1137   // Backing store for added metadata.
1138   BackingType unknown_;
1139 };
1140 
1141 // Given a factory template Factory, construct a type that derives from
1142 // Factory<MetadataTrait, MetadataTrait::CompressionTraits> for all
1143 // MetadataTraits. Useful for transports in defining the stateful parts of their
1144 // compression algorithm.
1145 template <template <typename, typename> class Factory,
1146           typename... MetadataTraits>
1147 struct StatefulCompressor;
1148 
1149 template <template <typename, typename> class Factory, typename MetadataTrait,
1150           bool kEncodable = IsEncodableTrait<MetadataTrait>::value>
1151 struct SpecificStatefulCompressor;
1152 
1153 template <template <typename, typename> class Factory, typename MetadataTrait>
1154 struct SpecificStatefulCompressor<Factory, MetadataTrait, true>
1155     : public Factory<MetadataTrait, typename MetadataTrait::CompressionTraits> {
1156 };
1157 
1158 template <template <typename, typename> class Factory, typename MetadataTrait>
1159 struct SpecificStatefulCompressor<Factory, MetadataTrait, false> {};
1160 
1161 template <template <typename, typename> class Factory, typename MetadataTrait,
1162           typename... MetadataTraits>
1163 struct StatefulCompressor<Factory, MetadataTrait, MetadataTraits...>
1164     : public SpecificStatefulCompressor<Factory, MetadataTrait>,
1165       public StatefulCompressor<Factory, MetadataTraits...> {};
1166 
1167 template <template <typename, typename> class Factory>
1168 struct StatefulCompressor<Factory> {};
1169 
1170 }  // namespace metadata_detail
1171 
1172 // Helper function for encoders
1173 // Given a metadata trait, convert the value to a slice.
1174 template <typename Which>
1175 absl::enable_if_t<std::is_same<typename Which::ValueType, Slice>::value,
1176                   const Slice&>
1177 MetadataValueAsSlice(const Slice& slice) {
1178   return slice;
1179 }
1180 
1181 template <typename Which>
1182 absl::enable_if_t<!std::is_same<typename Which::ValueType, Slice>::value, Slice>
1183 MetadataValueAsSlice(typename Which::ValueType value) {
1184   return Slice(Which::Encode(value));
1185 }
1186 
1187 // MetadataMap encodes the mapping of metadata keys to metadata values.
1188 //
1189 // MetadataMap takes a derived class and list of traits. Each of these trait
1190 // objects defines one metadata field that is used by core, and so should have
1191 // more specialized handling than just using the generic APIs.
1192 //
1193 // MetadataMap is the backing type for some derived type via the curiously
1194 // recursive template pattern. This is because many types consumed by
1195 // MetadataMap require the container type to operate on, and many of those
1196 // types are instantiated one per trait. A naive implementation without the
1197 // Derived type would, for traits A,B,C, then instantiate for some
1198 // T<Container, Trait>:
1199 //  - T<MetadataMap<A,B,C>, A>,
1200 //  - T<MetadataMap<A,B,C>, B>,
1201 //  - T<MetadataMap<A,B,C>, C>.
1202 // Since these types ultimately need to be recorded in the .dynstr segment
1203 // for dynamic linkers (if gRPC is linked as a static library) this would
1204 // create O(N^2) bytes of symbols even in stripped libraries. To avoid this
1205 // we use the derived type (e.g. grpc_metadata_batch right now) to capture
1206 // the container type, and we would write T<grpc_metadata_batch, A>, etc...
1207 // Note that now the container type uses a number of bytes that is independent
1208 // of the number of traits, and so we return to a linear symbol table growth
1209 // function.
1210 //
1211 // Each trait object has one of two possible signatures, depending on whether
1212 // that traits field is encodable or not.
1213 // Non-encodable traits are carried in a MetadataMap, but are never passed to
1214 // the application nor serialized to wire.
1215 //
1216 // Encodable traits have the following signature:
1217 // // Traits for the "grpc-xyz" metadata field:
1218 // struct GrpcXyzMetadata {
1219 //   // Can this metadata field be repeated?
1220 //   static constexpr bool kRepeatable = ...;
1221 //   // Should this metadata be transferred from server headers to trailers on
1222 //   // Trailers-Only response?
1223 //   static constexpr bool kTransferOnTrailersOnly = ...;
1224 //   // The type that's stored on MetadataBatch
1225 //   using ValueType = ...;
1226 //   // The type that's stored in compression/decompression tables
1227 //   using MementoType = ...;
1228 //   // The string key for this metadata type (for transports that require it)
1229 //   static absl::string_view key() { return "grpc-xyz"; }
1230 //   // Parse a memento from a slice
1231 //   // Takes ownership of value
1232 //   // If will_keep_past_request_lifetime is true, expect that the returned
1233 //   // memento will be kept for a long time, and so try not to keep a ref to
1234 //   // the input slice.
1235 //   // Calls fn in the case of an error that should be reported to the user
1236 //   static MementoType ParseMemento(
1237 //       Slice value,
1238 //       bool will_keep_past_request_lifetime,
1239 //       MementoParseErrorFn fn) {
1240 //   ...
1241 //   }
1242 //   // Convert a memento to a value
1243 //   static ValueType MementoToValue(MementoType memento) { ... }
1244 //   // Convert a value to its canonical text wire format (the format that
1245 //   // ParseMemento will accept!)
1246 //   static Slice Encode(const ValueType& value);
1247 //   // Convert a value to something that can be passed to StrCat and
1248 //   displayed
1249 //   // for debugging
1250 //   static SomeStrCatableType DisplayValue(ValueType value) { ... }
1251 //   static SomeStrCatableType DisplayMemento(MementoType value) { ... }
1252 // };
1253 //
1254 // Non-encodable traits are determined by missing the key() method, and have
1255 // the following signature (and by convention omit the Metadata part of the
1256 // type name):
1257 // // Traits for the GrpcXyz field:
1258 // struct GrpcXyz {
1259 //   // The string key that should be used for debug dumps - should not be a
1260 //   // valid http2 key (ie all lower case)
1261 //   static absl::string_view DebugKey() { return "GRPC_XYZ"; }
1262 //   // Can this metadata field be repeated?
1263 //   static constexpr bool kRepeatable = ...;
1264 //   // The type that's stored on MetadataBatch
1265 //   using ValueType = ...;
1266 //   // Convert a value to something that can be passed to StrCat and
1267 //   displayed
1268 //   // for debugging
1269 //   static SomeStrCatableType DisplayValue(ValueType value) { ... }
1270 // };
1271 //
1272 // About parsing and mementos:
1273 //
1274 // Many gRPC transports exchange metadata as key/value strings, but also allow
1275 // for a more efficient representation as a single integer. We can use this
1276 // integer representation to avoid reparsing too, by storing the parsed value
1277 // in the compression table. This is what mementos are used for.
1278 //
1279 // A trait offers the capability to turn a slice into a memento via
1280 // ParseMemento. This is exposed to users of MetadataMap via the Parse()
1281 // method, that returns a ParsedMetadata object. That ParsedMetadata object
1282 // can in turn be used to set the same value on many different MetadataMaps
1283 // without having to reparse.
1284 //
1285 // Implementation wise, ParsedMetadata is a type erased wrapper around
1286 // MementoType. When we set a value on MetadataMap, we first turn that memento
1287 // into a value. For most types, this is going to be a no-op, but for example
1288 // for grpc-timeout we make the memento the timeout expressed on the wire, but
1289 // we make the value the timestamp of when the timeout will expire (i.e. the
1290 // deadline).
1291 template <class Derived, typename... Traits>
1292 class MetadataMap {
1293  public:
1294   MetadataMap() = default;
1295   ~MetadataMap();
1296 
1297   // Given a compressor factory - template taking <MetadataTrait,
1298   // CompressionTrait>, StatefulCompressor<Factory> provides a type
1299   // derived from all Encodable traits in this MetadataMap.
1300   // This can be used by transports to delegate compression to the appropriate
1301   // compression algorithm.
1302   template <template <typename, typename> class Factory>
1303   using StatefulCompressor =
1304       metadata_detail::StatefulCompressor<Factory, Traits...>;
1305 
1306   MetadataMap(const MetadataMap&) = delete;
1307   MetadataMap& operator=(const MetadataMap&) = delete;
1308   MetadataMap(MetadataMap&&) noexcept;
1309   // We never create MetadataMap directly, instead we create Derived, but we
1310   // want to be able to move it without redeclaring this.
1311   // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1312   Derived& operator=(MetadataMap&&) noexcept;
1313 
1314   // Encode this metadata map into some encoder.
1315   // For each field that is set in the MetadataMap, call
1316   // encoder->Encode.
1317   //
1318   // For fields for which we have traits, this will be a method with
1319   // the signature:
1320   //    void Encode(TraitsType, typename TraitsType::ValueType value);
1321   // For fields for which we do not have traits, this will be a method
1322   // with the signature:
1323   //    void Encode(string_view key, Slice value);
1324   template <typename Encoder>
1325   void Encode(Encoder* encoder) const {
1326     table_.template ForEachIn<metadata_detail::EncodeWrapper<Encoder>,
1327                               Value<Traits>...>(
1328         metadata_detail::EncodeWrapper<Encoder>{encoder});
1329     for (const auto& unk : unknown_) {
1330       encoder->Encode(unk.first, unk.second);
1331     }
1332   }
1333 
1334   // Like Encode, but also visit the non-encodable fields.
1335   template <typename Encoder>
1336   void ForEach(Encoder* encoder) const {
1337     table_.ForEach(metadata_detail::ForEachWrapper<Encoder>{encoder});
1338     for (const auto& unk : unknown_) {
1339       encoder->Encode(unk.first, unk.second);
1340     }
1341   }
1342 
1343   // Similar to Encode, but targeted at logging: for each metadatum,
1344   // call f(key, value) as absl::string_views.
1345   void Log(metadata_detail::LogFn log_fn) const {
1346     table_.ForEach(metadata_detail::LogWrapper{log_fn});
1347     for (const auto& unk : unknown_) {
1348       log_fn(unk.first.as_string_view(), unk.second.as_string_view());
1349     }
1350   }
1351 
1352   // Filter the metadata map.
1353   // Iterates over all encodable and unknown headers and calls the filter_fn
1354   // for each of them. If the function returns true, the header is kept.
1355   template <typename Filterer>
1356   void Filter(Filterer filter_fn) {
1357     table_.template FilterIn<metadata_detail::FilterWrapper<Filterer>,
1358                              Value<Traits>...>(
1359         metadata_detail::FilterWrapper<Filterer>{filter_fn});
1360     unknown_.Filter<Filterer>(&filter_fn);
1361   }
1362 
1363   std::string DebugString() const {
1364     metadata_detail::DebugStringBuilder builder;
1365     Log([&builder](absl::string_view key, absl::string_view value) {
1366       builder.AddAfterRedaction(key, value);
1367     });
1368     return builder.TakeOutput();
1369   }
1370 
1371   template <typename Sink>
1372   friend void AbslStringify(Sink& sink, const MetadataMap& map) {
1373     sink.Append(map.DebugString());
1374   }
1375 
1376   // Get the pointer to the value of some known metadata.
1377   // Returns nullptr if the metadata is not present.
1378   // Causes a compilation error if Which is not an element of Traits.
1379   template <typename Which>
1380   const typename metadata_detail::Value<Which>::StorageType* get_pointer(
1381       Which) const {
1382     if (auto* p = table_.template get<Value<Which>>()) return &p->value;
1383     return nullptr;
1384   }
1385 
1386   // Get the pointer to the value of some known metadata.
1387   // Returns nullptr if the metadata is not present.
1388   // Causes a compilation error if Which is not an element of Traits.
1389   template <typename Which>
1390   typename metadata_detail::Value<Which>::StorageType* get_pointer(Which) {
1391     if (auto* p = table_.template get<Value<Which>>()) return &p->value;
1392     return nullptr;
1393   }
1394 
1395   // Get the pointer to the value of some known metadata.
1396   // Adds the default value for the metadata is not present.
1397   // Causes a compilation error if Which is not an element of Traits.
1398   template <typename Which>
1399   typename metadata_detail::Value<Which>::StorageType* GetOrCreatePointer(
1400       Which) {
1401     return &table_.template get_or_create<Value<Which>>()->value;
1402   }
1403 
1404   // Get the value of some known metadata.
1405   // Returns nullopt if the metadata is not present.
1406   // Causes a compilation error if Which is not an element of Traits.
1407   template <typename Which>
1408   absl::optional<typename Which::ValueType> get(Which) const {
1409     if (auto* p = table_.template get<Value<Which>>()) return p->value;
1410     return absl::nullopt;
1411   }
1412 
1413   // Set the value of some known metadata.
1414   // Returns a pointer to the new value.
1415   template <typename Which, typename... Args>
1416   absl::enable_if_t<Which::kRepeatable == false, void> Set(Which,
1417                                                            Args&&... args) {
1418     table_.template set<Value<Which>>(std::forward<Args>(args)...);
1419   }
1420   template <typename Which, typename... Args>
1421   absl::enable_if_t<Which::kRepeatable == true, void> Set(Which,
1422                                                           Args&&... args) {
1423     GetOrCreatePointer(Which())->emplace_back(std::forward<Args>(args)...);
1424   }
1425 
1426   // Remove a specific piece of known metadata.
1427   template <typename Which>
1428   void Remove(Which) {
1429     table_.template clear<Value<Which>>();
1430   }
1431 
1432   // Remove some metadata by name
1433   void Remove(absl::string_view key) {
1434     metadata_detail::RemoveHelper<Derived> helper(static_cast<Derived*>(this));
1435     metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
1436   }
1437 
1438   void Remove(const char* key) { Remove(absl::string_view(key)); }
1439 
1440   // Retrieve some metadata by name
1441   absl::optional<absl::string_view> GetStringValue(absl::string_view name,
1442                                                    std::string* buffer) const {
1443     metadata_detail::GetStringValueHelper<Derived> helper(
1444         static_cast<const Derived*>(this), buffer);
1445     return metadata_detail::NameLookup<Traits...>::Lookup(name, &helper);
1446   }
1447 
1448   // Extract a piece of known metadata.
1449   // Returns nullopt if the metadata was not present, or the value if it was.
1450   // The same as:
1451   //  auto value = m.get(T());
1452   //  m.Remove(T());
1453   template <typename Which>
1454   absl::enable_if_t<Which::kRepeatable == false,
1455                     absl::optional<typename Which::ValueType>>
1456   Take(Which which) {
1457     if (auto* p = get_pointer(which)) {
1458       absl::optional<typename Which::ValueType> value(std::move(*p));
1459       Remove(which);
1460       return value;
1461     }
1462     return {};
1463   }
1464 
1465   // Extract repeated known metadata.
1466   // Returns an empty vector if the metadata was not present.
1467   template <typename Which>
1468   absl::enable_if_t<Which::kRepeatable == true,
1469                     typename metadata_detail::Value<Which>::StorageType>
1470   Take(Which which) {
1471     if (auto* p = get_pointer(which)) {
1472       typename Value<Which>::StorageType value = std::move(*p);
1473       Remove(which);
1474       return value;
1475     }
1476     return {};
1477   }
1478 
1479   // Parse metadata from a key/value pair, and return an object representing
1480   // that result.
1481   static ParsedMetadata<Derived> Parse(absl::string_view key, Slice value,
1482                                        bool will_keep_past_request_lifetime,
1483                                        uint32_t transport_size,
1484                                        MetadataParseErrorFn on_error) {
1485     metadata_detail::ParseHelper<Derived> helper(
1486         value.TakeOwned(), will_keep_past_request_lifetime, on_error,
1487         transport_size);
1488     return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
1489   }
1490 
1491   // Set a value from a parsed metadata object.
1492   void Set(const ParsedMetadata<Derived>& m) {
1493     m.SetOnContainer(static_cast<Derived*>(this));
1494   }
1495 
1496   // Append a key/value pair - takes ownership of value
1497   void Append(absl::string_view key, Slice value,
1498               MetadataParseErrorFn on_error) {
1499     metadata_detail::AppendHelper<Derived> helper(static_cast<Derived*>(this),
1500                                                   value.TakeOwned(), on_error);
1501     metadata_detail::NameLookup<Traits...>::Lookup(key, &helper);
1502   }
1503 
1504   void Clear();
1505   size_t TransportSize() const;
1506   Derived Copy() const;
1507   bool empty() const { return table_.empty() && unknown_.empty(); }
1508   size_t count() const { return table_.count() + unknown_.size(); }
1509 
1510  private:
1511   friend class metadata_detail::AppendHelper<Derived>;
1512   friend class metadata_detail::GetStringValueHelper<Derived>;
1513   friend class metadata_detail::RemoveHelper<Derived>;
1514   friend class metadata_detail::CopySink<Derived>;
1515   friend class ParsedMetadata<Derived>;
1516 
1517   template <typename Which>
1518   using Value = metadata_detail::Value<Which>;
1519 
1520   // Table of known metadata types.
1521   PackedTable<Value<Traits>...> table_;
1522   metadata_detail::UnknownMap unknown_;
1523 };
1524 
1525 // Ok/not-ok check for metadata maps that contain GrpcStatusMetadata, so that
1526 // they can be used as result types for TrySeq.
1527 template <typename Derived, typename... Args>
1528 inline bool IsStatusOk(const MetadataMap<Derived, Args...>& m) {
1529   return m.get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
1530          GRPC_STATUS_OK;
1531 }
1532 
1533 template <typename Derived, typename... Traits>
1534 MetadataMap<Derived, Traits...>::MetadataMap(MetadataMap&& other) noexcept
1535     : table_(std::move(other.table_)), unknown_(std::move(other.unknown_)) {}
1536 
1537 // We never create MetadataMap directly, instead we create Derived, but we
1538 // want to be able to move it without redeclaring this.
1539 // NOLINTNEXTLINE(misc-unconventional-assign-operator)
1540 template <typename Derived, typename... Traits>
1541 Derived& MetadataMap<Derived, Traits...>::operator=(
1542     MetadataMap&& other) noexcept {
1543   table_ = std::move(other.table_);
1544   unknown_ = std::move(other.unknown_);
1545   return static_cast<Derived&>(*this);
1546 }
1547 
1548 template <typename Derived, typename... Traits>
1549 MetadataMap<Derived, Traits...>::~MetadataMap() = default;
1550 
1551 template <typename Derived, typename... Traits>
1552 void MetadataMap<Derived, Traits...>::Clear() {
1553   table_.ClearAll();
1554   unknown_.Clear();
1555 }
1556 
1557 template <typename Derived, typename... Traits>
1558 size_t MetadataMap<Derived, Traits...>::TransportSize() const {
1559   metadata_detail::TransportSizeEncoder enc;
1560   Encode(&enc);
1561   return enc.size();
1562 }
1563 
1564 template <typename Derived, typename... Traits>
1565 Derived MetadataMap<Derived, Traits...>::Copy() const {
1566   Derived out;
1567   metadata_detail::CopySink<Derived> sink(&out);
1568   ForEach(&sink);
1569   return out;
1570 }
1571 
1572 }  // namespace grpc_core
1573 
1574 struct grpc_metadata_batch;
1575 
1576 using grpc_metadata_batch_base = grpc_core::MetadataMap<
1577     grpc_metadata_batch,
1578     // Colon prefixed headers first
1579     grpc_core::HttpPathMetadata, grpc_core::HttpAuthorityMetadata,
1580     grpc_core::HttpMethodMetadata, grpc_core::HttpStatusMetadata,
1581     grpc_core::HttpSchemeMetadata,
1582     // Non-colon prefixed headers begin here
1583     grpc_core::ContentTypeMetadata, grpc_core::TeMetadata,
1584     grpc_core::GrpcEncodingMetadata, grpc_core::GrpcInternalEncodingRequest,
1585     grpc_core::GrpcAcceptEncodingMetadata, grpc_core::GrpcStatusMetadata,
1586     grpc_core::GrpcTimeoutMetadata, grpc_core::GrpcPreviousRpcAttemptsMetadata,
1587     grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::UserAgentMetadata,
1588     grpc_core::GrpcMessageMetadata, grpc_core::HostMetadata,
1589     grpc_core::EndpointLoadMetricsBinMetadata,
1590     grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata,
1591     grpc_core::GrpcTagsBinMetadata, grpc_core::GrpcLbClientStatsMetadata,
1592     grpc_core::LbCostBinMetadata, grpc_core::LbTokenMetadata,
1593     grpc_core::XEnvoyPeerMetadata, grpc_core::W3CTraceParentMetadata,
1594     // Non-encodable things
1595     grpc_core::GrpcStreamNetworkState, grpc_core::PeerString,
1596     grpc_core::GrpcStatusContext, grpc_core::GrpcStatusFromWire,
1597     grpc_core::GrpcCallWasCancelled, grpc_core::WaitForReady,
1598     grpc_core::IsTransparentRetry, grpc_core::GrpcTrailersOnly,
1599     grpc_core::GrpcTarPit,
1600     grpc_core::GrpcRegisteredMethod GRPC_CUSTOM_CLIENT_METADATA
1601         GRPC_CUSTOM_SERVER_METADATA>;
1602 
1603 struct grpc_metadata_batch : public grpc_metadata_batch_base {
1604   using grpc_metadata_batch_base::grpc_metadata_batch_base;
1605 };
1606 
1607 #endif  // GRPC_SRC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
1608