#pragma once #include #include #include namespace NGrpc { /** * Universal response that owns underlying message or buffer. */ template class TUniversalResponse: public TAtomicRefCount>, public TMoveOnly { friend class grpc::SerializationTraits>; public: explicit TUniversalResponse(NProtoBuf::Message* msg) noexcept : Data_{TMsg{}} { std::get(Data_).Swap(static_cast(msg)); } explicit TUniversalResponse(grpc::ByteBuffer* buffer) noexcept : Data_{grpc::ByteBuffer{}} { std::get(Data_).Swap(buffer); } private: std::variant Data_; }; /** * Universal response that only keeps reference to underlying message or buffer. */ template class TUniversalResponseRef: private TMoveOnly { friend class grpc::SerializationTraits>; public: explicit TUniversalResponseRef(const NProtoBuf::Message* msg) : Data_{msg} { } explicit TUniversalResponseRef(const grpc::ByteBuffer* buffer) : Data_{buffer} { } private: std::variant Data_; }; } // namespace NGrpc namespace grpc { template class SerializationTraits> { public: static Status Serialize( const NGrpc::TUniversalResponse& resp, ByteBuffer* buffer, bool* ownBuffer) { return std::visit([&](const auto& data) { using T = std::decay_t; return SerializationTraits::Serialize(data, buffer, ownBuffer); }, resp.Data_); } }; template class SerializationTraits> { public: static Status Serialize( const NGrpc::TUniversalResponseRef& resp, ByteBuffer* buffer, bool* ownBuffer) { return std::visit([&](const auto* data) { using T = std::decay_t>; return SerializationTraits::Serialize(*data, buffer, ownBuffer); }, resp.Data_); } }; } // namespace grpc