#pragma once #include #include #include #include namespace NKikimr::NMiniKQL::NMatchRecognize { struct TSerializerContext { TSerializerContext( TComputationContext& ctx, TType* rowType, const TMutableObjectOverBoxedValue& rowPacker) : Ctx(ctx) , RowType(rowType) , RowPacker(rowPacker) {} TComputationContext& Ctx; TType* RowType; const TMutableObjectOverBoxedValue& RowPacker; }; template inline constexpr bool always_false_v = false; struct TMrOutputSerializer : TOutputSerializer { private: enum class TPtrStateMode { Saved = 0, FromCache = 1 }; public: TMrOutputSerializer(const TSerializerContext& context, EMkqlStateType stateType, ui32 stateVersion, TComputationContext& ctx) : TOutputSerializer(stateType, stateVersion, ctx) , Context(context) {} using TOutputSerializer::Write; template void operator()(Ts&&... args) { (Write(std::forward(args)), ...); } void Write(const NUdf::TUnboxedValue& value) { WriteUnboxedValue(Context.RowPacker.RefMutableObject(Context.Ctx, false, Context.RowType), value); } template void Write(const TIntrusivePtr& ptr) { bool isValid = static_cast(ptr); WriteBool(Buf, isValid); if (!isValid) { return; } auto addr = reinterpret_cast(ptr.Get()); WriteUi64(Buf, addr); auto it = Cache.find(addr); if (it != Cache.end()) { WriteByte(Buf, static_cast(TPtrStateMode::FromCache)); return; } WriteByte(Buf, static_cast(TPtrStateMode::Saved)); ptr->Save(*this); Cache[addr] = addr; } private: const TSerializerContext& Context; mutable std::map Cache; }; struct TMrInputSerializer : TInputSerializer { private: enum class TPtrStateMode { Saved = 0, FromCache = 1 }; public: TMrInputSerializer(TSerializerContext& context, const NUdf::TUnboxedValue& state) : TInputSerializer(state, EMkqlStateType::SIMPLE_BLOB) , Context(context) { } using TInputSerializer::Read; template void operator()(Ts&... args) { (Read(args), ...); } void Read(NUdf::TUnboxedValue& value) { value = ReadUnboxedValue(Context.RowPacker.RefMutableObject(Context.Ctx, false, Context.RowType), Context.Ctx); } template void Read(TIntrusivePtr& ptr) { bool isValid = Read(); if (!isValid) { ptr.Reset(); return; } ui64 addr = Read(); TPtrStateMode mode = static_cast(Read()); if (mode == TPtrStateMode::Saved) { ptr = MakeIntrusive(); ptr->Load(*this); Cache[addr] = ptr.Get(); return; } auto it = Cache.find(addr); MKQL_ENSURE(it != Cache.end(), "Internal error"); auto* cachePtr = static_cast(it->second); ptr = TIntrusivePtr(cachePtr); } private: TSerializerContext& Context; mutable std::map Cache; }; } //namespace NKikimr::NMiniKQL::NMatchRecognize