#pragma once #include #include namespace NYql::NPureCalc::NPrivate { using TProtoRawMultiOutput = std::pair; template using TProtoMultiOutput = std::variant; template using TProtoOutput = std::add_pointer_t::template TGet>; template TProtoMultiOutput InitProtobufsVariant(google::protobuf::Message* ptr) { static_assert(std::conjunction_v...>); return TProtoMultiOutput(std::in_place_index, static_cast>(ptr)); } template class TProtobufsMappingBase { public: TProtobufsMappingBase() : InitFuncs_(BuildInitFuncs(std::make_index_sequence())) { } private: typedef TProtoMultiOutput (*initfunc)(google::protobuf::Message*); template inline std::array BuildInitFuncs(std::index_sequence) { return {&InitProtobufsVariant...}; } protected: const std::array InitFuncs_; }; template class TProtobufsMappingStream: public IStream>, public TProtobufsMappingBase { public: TProtobufsMappingStream(THolder> oldStream) : OldStream_(std::move(oldStream)) { } public: TProtoMultiOutput Fetch() override { auto&& oldItem = OldStream_->Fetch(); return this->InitFuncs_[oldItem.first](oldItem.second); } private: THolder> OldStream_; }; template class TProtobufsMappingConsumer: public IConsumer, public TProtobufsMappingBase { public: TProtobufsMappingConsumer(THolder>> oldConsumer) : OldConsumer_(std::move(oldConsumer)) { } public: void OnObject(TProtoRawMultiOutput oldItem) override { OldConsumer_->OnObject(this->InitFuncs_[oldItem.first](oldItem.second)); } void OnFinish() override { OldConsumer_->OnFinish(); } private: THolder>> OldConsumer_; }; }