parsed_metadata.h
Go to the documentation of this file.
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_CORE_LIB_TRANSPORT_PARSED_METADATA_H
16 #define GRPC_CORE_LIB_TRANSPORT_PARSED_METADATA_H
17 
19 
20 #include <string.h>
21 
22 #include <cstdint>
23 #include <string>
24 #include <type_traits>
25 #include <utility>
26 
27 #include "absl/functional/function_ref.h"
28 #include "absl/meta/type_traits.h"
29 #include "absl/strings/match.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 
33 #include <grpc/slice.h>
34 
37 
38 namespace grpc_core {
39 
42 
43 namespace metadata_detail {
44 
45 // Helper to determine whether a traits metadata is inlinable inside a memento,
46 // or (if not) we'll need to take the memory allocation path.
47 template <typename Which>
49  static constexpr bool value =
51  sizeof(typename Which::MementoType) <= sizeof(grpc_slice)) ||
53 };
54 
55 // Storage type for a single metadata entry.
56 union Buffer {
58  void* pointer;
60 };
61 
62 // Given a key and a value, concatenate together to make a debug string.
63 // Split out to avoid template bloat.
65 
66 // Wrapper around MakeDebugString.
67 // For the value part, use two functions - one to extract a typed field from
68 // Buffer, and a second (sourced from the trait) to generate a displayable debug
69 // string from the field value. We try to maximize indirection/code sharing here
70 // as this is not critical path code and we'd like to avoid some code bloat -
71 // better to scale by number of types than then number of metadata traits!
72 template <typename Field, typename CompatibleWithField, typename Display>
75  Field (*field_from_buffer)(const Buffer&),
76  Display (*display_from_field)(CompatibleWithField)) {
77  return MakeDebugString(
78  key, absl::StrCat(display_from_field(field_from_buffer(value))));
79 }
80 
81 // Extract a trivial field value from a Buffer - for MakeDebugStringPipeline.
82 template <typename Field>
84  Field field;
85  memcpy(&field, value.trivial, sizeof(Field));
86  return field;
87 }
88 
89 // Extract a pointer field value from a Buffer - for MakeDebugStringPipeline.
90 template <typename Field>
92  return *static_cast<const Field*>(value.pointer);
93 }
94 
95 // Extract a Slice from a Buffer.
96 Slice SliceFromBuffer(const Buffer& buffer);
97 
98 // Unref the grpc_slice part of a Buffer (assumes it is in fact a grpc_slice).
99 void DestroySliceValue(const Buffer& value);
100 
101 // Destroy a trivial memento (empty function).
102 void DestroyTrivialMemento(const Buffer& value);
103 
104 // Set a slice value in a container
105 template <Slice (*MementoToValue)(Slice)>
107  *set = MementoToValue(SliceFromBuffer(value));
108 }
109 
110 } // namespace metadata_detail
111 
112 // A parsed metadata value.
113 // This type captures a type erased MementoType from one trait of
114 // MetadataContainer, and provides utilities to manipulate that and to set it on
115 // a MetadataContainer.
116 template <typename MetadataContainer>
118  public:
119  // Construct metadata from a trait Which of MetadataContainer.
120  // Two versions: the first is for simple inlinable mementos, and the second
121  // forces an allocation.
122  template <typename Which>
124  Which,
126  typename Which::MementoType>
127  value,
131  memcpy(value_.trivial, &value, sizeof(value));
132  }
133  template <typename Which>
135  Which,
139  typename Which::MementoType>
140  value,
144  value_.pointer = new typename Which::MementoType(std::move(value));
145  }
146  // Construct metadata from a Slice typed value.
147  template <typename Which>
151  value_.slice = value.TakeCSlice();
152  }
153  // Construct metadata from a string key, slice value pair.
155  : vtable_(ParsedMetadata::KeyValueVTable(key.as_string_view())),
156  transport_size_(key.size() + value.size() + 32) {
157  value_.pointer =
158  new std::pair<Slice, Slice>(std::move(key), std::move(value));
159  }
162 
163  // Non copyable, but movable.
164  ParsedMetadata(const ParsedMetadata&) = delete;
165  ParsedMetadata& operator=(const ParsedMetadata&) = delete;
166  ParsedMetadata(ParsedMetadata&& other) noexcept
167  : vtable_(other.vtable_),
168  value_(other.value_),
169  transport_size_(other.transport_size_) {
170  other.vtable_ = EmptyVTable();
171  }
173  vtable_ = other.vtable_;
174  value_ = other.value_;
175  transport_size_ = other.transport_size_;
176  other.vtable_ = EmptyVTable();
177  return *this;
178  }
179 
180  // Set this parsed value on a container.
181  void SetOnContainer(MetadataContainer* container) const {
183  }
184 
185  // Is this a binary header or not?
186  bool is_binary_header() const { return vtable_->is_binary_header; }
187  // HTTP2 defined storage size of this metadatum.
189  // Create a new parsed metadata with the same key but a different value.
191  MetadataParseErrorFn on_error) const {
193  result.vtable_ = vtable_;
194  result.value_ = value_;
195  result.transport_size_ = TransportSize(key().length(), value.length());
196  vtable_->with_new_value(&value, on_error, &result);
197  return result;
198  }
201  if (vtable_->key == nullptr) return vtable_->key_value;
202  return vtable_->key(value_);
203  }
204 
205  // TODO(ctiller): move to transport
206  static uint32_t TransportSize(uint32_t key_size, uint32_t value_size) {
207  // TODO(ctiller): use hpack constant?
208  return key_size + value_size + 32;
209  }
210 
211  private:
213 
214  struct VTable {
215  const bool is_binary_header;
216  void (*const destroy)(const Buffer& value);
217  void (*const set)(const Buffer& value, MetadataContainer* container);
218  // result is a bitwise copy of the originating ParsedMetadata.
219  void (*const with_new_value)(Slice* new_value,
220  MetadataParseErrorFn on_error,
223  // The key - if key is null, use key_value, otherwise call key.
225  absl::string_view (*const key)(const Buffer& value);
226  };
227 
228  static const VTable* EmptyVTable();
230  template <typename Which>
231  static const VTable* TrivialTraitVTable();
232  template <typename Which>
233  static const VTable* NonTrivialTraitVTable();
234  template <typename Which>
235  static const VTable* SliceTraitVTable();
236 
237  template <Slice (*ParseMemento)(Slice, MetadataParseErrorFn)>
240  result->value_.slice =
241  ParseMemento(std::move(*slice), on_error).TakeCSlice();
242  }
243 
244  template <typename T, T (*ParseMemento)(Slice, MetadataParseErrorFn)>
247  T memento = ParseMemento(std::move(*slice), on_error);
248  memcpy(result->value_.trivial, &memento, sizeof(memento));
249  }
250 
251  const VTable* vtable_;
254 };
255 
256 namespace metadata_detail {} // namespace metadata_detail
257 
258 template <typename MetadataContainer>
259 const typename ParsedMetadata<MetadataContainer>::VTable*
261  static const VTable vtable = {
262  false,
263  // destroy
265  // set
266  [](const Buffer&, MetadataContainer*) {},
267  // with_new_value
269  // debug_string
270  [](const Buffer&) -> std::string { return "empty"; },
271  // key
272  "",
273  nullptr,
274  };
275  return &vtable;
276 }
277 
278 template <typename MetadataContainer>
279 template <typename Which>
282  static const VTable vtable = {
283  absl::EndsWith(Which::key(), "-bin"),
284  // destroy
286  // set
287  [](const Buffer& value, MetadataContainer* map) {
288  map->Set(
289  Which(),
290  Which::MementoToValue(
291  metadata_detail::FieldFromTrivial<typename Which::MementoType>(
292  value)));
293  },
294  // with_new_value
295  WithNewValueSetTrivial<typename Which::MementoType, Which::ParseMemento>,
296  // debug_string
297  [](const Buffer& value) {
299  Which::key(), value,
300  metadata_detail::FieldFromTrivial<typename Which::MementoType>,
301  Which::DisplayValue);
302  },
303  // key
304  Which::key(),
305  nullptr,
306  };
307  return &vtable;
308 }
309 
310 template <typename MetadataContainer>
311 template <typename Which>
314  static const VTable vtable = {
315  absl::EndsWith(Which::key(), "-bin"),
316  // destroy
317  [](const Buffer& value) {
318  delete static_cast<typename Which::MementoType*>(value.pointer);
319  },
320  // set
321  [](const Buffer& value, MetadataContainer* map) {
322  auto* p = static_cast<typename Which::MementoType*>(value.pointer);
323  map->Set(Which(), Which::MementoToValue(*p));
324  },
325  // with_new_value
327  result->value_.pointer = new typename Which::MementoType(
328  Which::ParseMemento(std::move(*value), on_error));
329  },
330  // debug_string
331  [](const Buffer& value) {
333  Which::key(), value,
334  metadata_detail::FieldFromPointer<typename Which::MementoType>,
335  Which::DisplayValue);
336  },
337  // key
338  Which::key(),
339  nullptr,
340  };
341  return &vtable;
342 }
343 
344 template <typename MetadataContainer>
345 template <typename Which>
348  static const VTable vtable = {
349  absl::EndsWith(Which::key(), "-bin"),
350  // destroy
352  // set
353  [](const Buffer& value, MetadataContainer* map) {
354  metadata_detail::SetSliceValue<Which::MementoToValue>(
355  map->GetOrCreatePointer(Which()), value);
356  },
357  // with_new_value
358  WithNewValueSetSlice<Which::ParseMemento>,
359  // debug_string
360  [](const Buffer& value) {
363  Which::DisplayValue);
364  },
365  // key
366  Which::key(),
367  nullptr,
368  };
369  return &vtable;
370 }
371 
372 template <typename MetadataContainer>
375  using KV = std::pair<Slice, Slice>;
376  static const auto destroy = [](const Buffer& value) {
377  delete static_cast<KV*>(value.pointer);
378  };
379  static const auto set = [](const Buffer& value, MetadataContainer* map) {
380  auto* p = static_cast<KV*>(value.pointer);
381  map->unknown_.Append(p->first.as_string_view(), p->second.Ref());
382  };
383  static const auto with_new_value = [](Slice* value, MetadataParseErrorFn,
385  auto* p = new KV{
386  static_cast<KV*>(result->value_.pointer)->first.Ref(),
387  std::move(*value),
388  };
389  result->value_.pointer = p;
390  };
391  static const auto debug_string = [](const Buffer& value) {
392  auto* p = static_cast<KV*>(value.pointer);
393  return absl::StrCat(p->first.as_string_view(), ": ",
394  p->second.as_string_view());
395  };
396  static const auto key_fn = [](const Buffer& value) {
397  return static_cast<KV*>(value.pointer)->first.as_string_view();
398  };
399  static const VTable vtable[2] = {
400  {false, destroy, set, with_new_value, debug_string, "", key_fn},
401  {true, destroy, set, with_new_value, debug_string, "", key_fn},
402  };
403  return &vtable[absl::EndsWith(key, "-bin")];
404 }
405 
406 } // namespace grpc_core
407 
408 #endif // GRPC_CORE_LIB_TRANSPORT_PARSED_METADATA_H
slice.h
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
grpc_core::metadata_detail::HasSimpleMemento::value
static constexpr bool value
Definition: parsed_metadata.h:49
vtable
static const grpc_transport_vtable vtable
Definition: binder_transport.cc:680
grpc_core::ParsedMetadata::VTable::debug_string
std::string(*const debug_string)(const Buffer &value)
Definition: parsed_metadata.h:222
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
grpc_core::ParsedMetadata::WithNewValue
ParsedMetadata WithNewValue(Slice value, MetadataParseErrorFn on_error) const
Definition: parsed_metadata.h:190
grpc_core::metadata_detail::FieldFromPointer
Field FieldFromPointer(const Buffer &value)
Definition: parsed_metadata.h:91
slice.h
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::ParsedMetadata::NonTrivialTraitVTable
static const VTable * NonTrivialTraitVTable()
Definition: parsed_metadata.h:313
grpc_core::Slice
Definition: src/core/lib/slice/slice.h:282
grpc_core::ParsedMetadata::ParsedMetadata
ParsedMetadata(Slice key, Slice value)
Definition: parsed_metadata.h:154
string.h
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
grpc_core::ParsedMetadata::TrivialTraitVTable
static const VTable * TrivialTraitVTable()
Definition: parsed_metadata.h:281
grpc_core::ParsedMetadata::SliceTraitVTable
static const VTable * SliceTraitVTable()
Definition: parsed_metadata.h:347
grpc_core::ParsedMetadata::KeyValueVTable
static const VTable * KeyValueVTable(absl::string_view key)
Definition: parsed_metadata.h:374
grpc_core::ParsedMetadata::SetOnContainer
void SetOnContainer(MetadataContainer *container) const
Definition: parsed_metadata.h:181
grpc_core::ParsedMetadata::VTable::set
void(*const set)(const Buffer &value, MetadataContainer *container)
Definition: parsed_metadata.h:217
grpc_core::ParsedMetadata::DebugString
std::string DebugString() const
Definition: parsed_metadata.h:199
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
grpc_core::ParsedMetadata::VTable::key_value
absl::string_view key_value
Definition: parsed_metadata.h:224
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
T
#define T(upbtypeconst, upbtype, ctype, default_value)
grpc_core::ParsedMetadata::ParsedMetadata
ParsedMetadata()
Definition: parsed_metadata.h:160
grpc_core::ParsedMetadata::EmptyVTable
static const VTable * EmptyVTable()
Definition: parsed_metadata.h:260
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
grpc_core::metadata_detail::DestroyTrivialMemento
void DestroyTrivialMemento(const Buffer &)
Definition: parsed_metadata.cc:36
grpc_core::ParsedMetadata::value_
Buffer value_
Definition: parsed_metadata.h:252
grpc_core::ParsedMetadata::VTable::destroy
void(*const destroy)(const Buffer &value)
Definition: parsed_metadata.h:216
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
grpc_core::ParsedMetadata::operator=
ParsedMetadata & operator=(const ParsedMetadata &)=delete
grpc_slice
struct grpc_slice grpc_slice
Definition: include/grpc/impl/codegen/slice.h:30
grpc_core::metadata_detail::Buffer::pointer
void * pointer
Definition: parsed_metadata.h:58
slice
grpc_slice slice
Definition: src/core/lib/surface/server.cc:467
grpc_core::ParsedMetadata::vtable_
const VTable * vtable_
Definition: parsed_metadata.h:251
grpc_core::metadata_detail::MakeDebugStringPipeline
GPR_ATTRIBUTE_NOINLINE std::string MakeDebugStringPipeline(absl::string_view key, const Buffer &value, Field(*field_from_buffer)(const Buffer &), Display(*display_from_field)(CompatibleWithField))
Definition: parsed_metadata.h:73
time.h
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
grpc_core::ParsedMetadata::operator=
ParsedMetadata & operator=(ParsedMetadata &&other) noexcept
Definition: parsed_metadata.h:172
grpc_core::ParsedMetadata::WithNewValueSetTrivial
static GPR_ATTRIBUTE_NOINLINE void WithNewValueSetTrivial(Slice *slice, MetadataParseErrorFn on_error, ParsedMetadata *result)
Definition: parsed_metadata.h:245
buffer
char buffer[1024]
Definition: libuv/docs/code/idle-compute/main.c:8
grpc_core::metadata_detail::Buffer::trivial
uint8_t trivial[sizeof(grpc_slice)]
Definition: parsed_metadata.h:57
grpc_core::ParsedMetadata
Definition: parsed_metadata.h:117
grpc_core::ParsedMetadata::transport_size_
uint32_t transport_size_
Definition: parsed_metadata.h:253
value
const char * value
Definition: hpack_parser_table.cc:165
grpc_core::ParsedMetadata::VTable::is_binary_header
const bool is_binary_header
Definition: parsed_metadata.h:215
grpc_core::ParsedMetadata::TransportSize
static uint32_t TransportSize(uint32_t key_size, uint32_t value_size)
Definition: parsed_metadata.h:206
field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc:2692
grpc_core::metadata_detail::MakeDebugString
std::string MakeDebugString(absl::string_view key, absl::string_view value)
Definition: parsed_metadata.cc:24
key
const char * key
Definition: hpack_parser_table.cc:164
grpc_core::ParsedMetadata::ParsedMetadata
ParsedMetadata(Which, absl::enable_if_t< metadata_detail::HasSimpleMemento< Which >::value, typename Which::MementoType > value, uint32_t transport_size)
Definition: parsed_metadata.h:123
grpc_core::ParsedMetadata::transport_size
uint32_t transport_size() const
Definition: parsed_metadata.h:188
grpc_core::ParsedMetadata::VTable
Definition: parsed_metadata.h:214
grpc_core::MetadataParseErrorFn
absl::FunctionRef< void(absl::string_view error, const Slice &value)> MetadataParseErrorFn
Definition: parsed_metadata.h:41
grpc_core::metadata_detail::Buffer::slice
grpc_slice slice
Definition: parsed_metadata.h:59
grpc_core::ParsedMetadata::is_binary_header
bool is_binary_header() const
Definition: parsed_metadata.h:186
string_view
absl::string_view string_view
Definition: attr.cc:22
first
StrT first
Definition: cxa_demangle.cpp:4884
grpc_core::metadata_detail::HasSimpleMemento
Definition: parsed_metadata.h:48
cpp.gmock_class.set
set
Definition: bloaty/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py:44
grpc_core::ParsedMetadata::ParsedMetadata
ParsedMetadata(Which, absl::enable_if_t< !metadata_detail::HasSimpleMemento< Which >::value &&!std::is_convertible< typename Which::MementoType, Slice >::value, typename Which::MementoType > value, uint32_t transport_size)
Definition: parsed_metadata.h:134
absl::FunctionRef
Definition: abseil-cpp/absl/functional/function_ref.h:65
grpc_core::ParsedMetadata::ParsedMetadata
ParsedMetadata(ParsedMetadata &&other) noexcept
Definition: parsed_metadata.h:166
grpc_core::ParsedMetadata::WithNewValueSetSlice
static GPR_ATTRIBUTE_NOINLINE void WithNewValueSetSlice(Slice *slice, MetadataParseErrorFn on_error, ParsedMetadata *result)
Definition: parsed_metadata.h:238
grpc_core::ParsedMetadata::VTable::with_new_value
void(*const with_new_value)(Slice *new_value, MetadataParseErrorFn on_error, ParsedMetadata *result)
Definition: parsed_metadata.h:219
Field
Definition: bloaty/third_party/protobuf/src/google/protobuf/type.pb.h:446
setup.template
template
Definition: setup.py:47
grpc_core::ParsedMetadata::ParsedMetadata
ParsedMetadata(Which, Slice value, uint32_t transport_size)
Definition: parsed_metadata.h:148
grpc_core::ParsedMetadata::VTable::key
absl::string_view(*const key)(const Buffer &value)
Definition: parsed_metadata.h:225
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
grpc_core::metadata_detail::DestroySliceValue
void DestroySliceValue(const Buffer &value)
Definition: parsed_metadata.cc:32
length
std::size_t length
Definition: abseil-cpp/absl/time/internal/test_util.cc:57
grpc_core::metadata_detail::SetSliceValue
void SetSliceValue(Slice *set, const Buffer &value)
Definition: parsed_metadata.h:106
grpc_core::ParsedMetadata::key
absl::string_view key() const
Definition: parsed_metadata.h:200
grpc_core::metadata_detail::Buffer
Definition: parsed_metadata.h:56
grpc_core::metadata_detail::FieldFromTrivial
Field FieldFromTrivial(const Buffer &value)
Definition: parsed_metadata.h:83
grpc_core::metadata_detail::SliceFromBuffer
Slice SliceFromBuffer(const Buffer &buffer)
Definition: parsed_metadata.cc:28
absl::EndsWith
bool EndsWith(absl::string_view text, absl::string_view suffix) noexcept
Definition: third_party/abseil-cpp/absl/strings/match.h:68
destroy
static std::function< void(void *, Slot *)> destroy
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:42
container
static struct async_container * container
Definition: benchmark-million-async.c:33
GPR_ATTRIBUTE_NOINLINE
#define GPR_ATTRIBUTE_NOINLINE
Definition: impl/codegen/port_platform.h:684
grpc_core::ParsedMetadata::~ParsedMetadata
~ParsedMetadata()
Definition: parsed_metadata.h:161
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:49