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