10#include <userver/utils/any_movable.hpp> 
   11#include <userver/utils/fast_pimpl.hpp> 
   13USERVER_NAMESPACE_BEGIN
 
   18class InternalRequestContext;
 
   25class RequestContext 
final {
 
   29  RequestContext(RequestContext&&) 
noexcept;
 
   31  RequestContext(
const RequestContext&) = 
delete;
 
   37  template <
typename Data>
 
   42  template <
typename Data, 
typename... Args>
 
   48  template <
typename Data>
 
   54  template <
typename Data>
 
   59  template <
typename Data>
 
   64  template <
typename Data>
 
   73  template <
typename Data>
 
   74  Data& 
SetData(std::string name, Data data);
 
   79  template <
typename Data, 
typename... Args>
 
   80  Data& 
EmplaceData(std::string name, Args&&... args);
 
   85  template <
typename Data>
 
   86  Data& 
GetData(std::string_view name);
 
   91  template <
typename Data>
 
   92  const Data& 
GetData(std::string_view name) 
const;
 
   96  template <
typename Data>
 
  101  template <
typename Data>
 
  109  impl::InternalRequestContext& GetInternalContext();
 
  112  utils::AnyMovable& SetUserAnyData(utils::AnyMovable&& data);
 
  113  utils::AnyMovable& GetUserAnyData();
 
  114  utils::AnyMovable* GetUserAnyDataOptional();
 
  115  void EraseUserAnyData();
 
  117  utils::AnyMovable& SetAnyData(std::string&& name, utils::AnyMovable&& data);
 
  118  utils::AnyMovable& GetAnyData(std::string_view name);
 
  119  utils::AnyMovable* GetAnyDataOptional(std::string_view name);
 
  120  void EraseAnyData(std::string_view name);
 
  123  static constexpr std::size_t kPimplSize = 112;
 
  124  utils::FastPimpl<Impl, kPimplSize, 
alignof(
void*)> impl_;
 
  127template <
typename Data>
 
  129  static_assert(!std::is_const_v<Data>,
 
  130                "Data stored in RequestContext is mutable if RequestContext is " 
  131                "not `const`. Remove the `const` from the template parameter " 
  132                "of SetUserData as it makes no sense");
 
  134      !std::is_reference_v<Data>,
 
  135      "Data in RequestContext is stored by copy. Remove the reference " 
  136      "from the template parameter of SetUserData as it makes no sense");
 
  137  return utils::AnyCast<Data&>(SetUserAnyData(std::move(data)));
 
  140template <
typename Data, 
typename... Args>
 
  143  auto& data = SetUserAnyData(Data(std::forward<Args>(args)...));
 
  144  return utils::AnyCast<Data&>(data);
 
  147template <
typename Data>
 
  149  return utils::AnyCast<Data&>(GetUserAnyData());
 
  152template <
typename Data>
 
  155  return const_cast<RequestContext*>(
this)->GetUserData<Data>();
 
  158template <
typename Data>
 
  160  auto* data = GetUserAnyDataOptional();
 
  161  return data ? &utils::AnyCast<Data&>(*data) : 
nullptr;
 
  164template <
typename Data>
 
  168  return const_cast<RequestContext*>(
this)->GetUserDataOptional<Data>();
 
  173template <
typename Data>
 
  174Data& RequestContext::
SetData(std::string name, Data data) {
 
  175  static_assert(!std::is_const_v<Data>,
 
  176                "Data stored in RequestContext is mutable if RequestContext is " 
  177                "not `const`. Remove the `const` from the template parameter " 
  178                "of SetData as it makes no sense");
 
  180      !std::is_reference_v<Data>,
 
  181      "Data in RequestContext is stored by copy. Remove the reference " 
  182      "from the template parameter of SetData as it makes no sense");
 
  183  return utils::AnyCast<Data&>(SetAnyData(std::move(name), std::move(data)));
 
  186template <
typename Data, 
typename... Args>
 
  187Data& RequestContext::
EmplaceData(std::string name, Args&&... args) {
 
  189  auto& data = SetAnyData(std::move(name), Data(std::forward<Args>(args)...));
 
  190  return utils::AnyCast<Data&>(data);
 
  193template <
typename Data>
 
  194Data& RequestContext::
GetData(std::string_view name) {
 
  195  return utils::AnyCast<Data&>(GetAnyData(name));
 
  198template <
typename Data>
 
  199const Data& RequestContext::
GetData(std::string_view name) 
const {
 
  201  return const_cast<RequestContext*>(
this)->GetData<Data>(name);
 
  204template <
typename Data>
 
  207  auto* data = GetAnyDataOptional(name);
 
  208  return data ? &utils::AnyCast<Data&>(*data) : 
nullptr;
 
  211template <
typename Data>
 
  215  return const_cast<RequestContext*>(
this)->GetDataOptional<Data>(name);
 
  218inline void RequestContext::
EraseData(std::string_view name) {