// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include ZEN_THIRD_PARTY_INCLUDES_START #include ZEN_THIRD_PARTY_INCLUDES_END namespace zen { #pragma pack(push) #pragma pack(1) struct ReferenceMetaDataHeader { static constexpr uint32_t Version1 = 1; static constexpr uint32_t CurrentVersion = Version1; ReferenceMetaDataHeader(uint32_t InMagic, uint32_t InEntryCount, uint64_t InAttachmentCount) : Magic(InMagic) , EntryCount(InEntryCount) , AttachmentCount(InAttachmentCount) , Checksum(ComputeChecksum()) { } uint32_t Magic = 0xffffffffu; uint32_t Version = CurrentVersion; uint32_t EntryCount = 0; uint64_t AttachmentCount = 0; uint64_t Padding = 0; uint32_t Checksum = 0; bool IsValid(uint32_t ExpectedMagic) const; template static uint64_t ExpectedSize(uint32_t EntryCount, uint64_t AttachmentCount) { return sizeof(ReferenceMetaDataHeader) + sizeof(KeyType) * EntryCount + sizeof(uint32_t) * EntryCount + sizeof(AttachmentType) * AttachmentCount; } ReferenceMetaDataHeader() = delete; private: uint32_t ComputeChecksum() const; }; static_assert(sizeof(ReferenceMetaDataHeader) == 32); #pragma pack(pop) template CompositeBuffer BuildReferenceMetaData(uint32_t HeaderMagic, std::span Keys, std::span AttachmentCounts, std::span Attachments) { uint32_t KeyCount = gsl::narrow(Keys.size()); ReferenceMetaDataHeader Header(HeaderMagic, KeyCount, Attachments.size()); return CompositeBuffer(std::vector{ SharedBuffer(IoBuffer(IoBuffer::Clone, &Header, sizeof(ReferenceMetaDataHeader))), SharedBuffer(IoBuffer(IoBuffer::Wrap, Keys.data(), sizeof(KeyType) * Keys.size())), SharedBuffer(IoBuffer(IoBuffer::Wrap, AttachmentCounts.data(), sizeof(uint32_t) * AttachmentCounts.size())), SharedBuffer(IoBuffer(IoBuffer::Wrap, Attachments.data(), sizeof(AttachmentType) * Attachments.size()))}); } template bool GetAttachmentsFromMetaData(const IoBuffer& MetaData, const uint32_t ExpectedHeaderMagic, std::function Keys, std::span AttachmentCounts, std::span Attachments)>&& Parser) { MemoryView PayloadView = MetaData.GetView(); if (PayloadView.GetSize() >= sizeof(ReferenceMetaDataHeader)) { const ReferenceMetaDataHeader* Header = (const ReferenceMetaDataHeader*)PayloadView.GetData(); if (Header->IsValid(ExpectedHeaderMagic)) { if (MetaData.GetSize() == ReferenceMetaDataHeader::ExpectedSize(Header->EntryCount, Header->AttachmentCount)) { PayloadView.MidInline(sizeof(ReferenceMetaDataHeader)); std::span PayloadKeys = {(const KeyType*)PayloadView.GetData(), Header->EntryCount}; PayloadView.MidInline(sizeof(KeyType) * Header->EntryCount); std::span PayloadAttachmentCounts = {(const uint32_t*)PayloadView.GetData(), Header->EntryCount}; PayloadView.MidInline(sizeof(uint32_t) * Header->EntryCount); std::span PayloadAttachments = {(const AttachmentType*)PayloadView.GetData(), Header->AttachmentCount}; PayloadView.MidInline(sizeof(AttachmentType) * Header->AttachmentCount); ZEN_ASSERT(PayloadView.GetSize() == 0); Parser(PayloadKeys, PayloadAttachmentCounts, PayloadAttachments); return true; } } } return false; } } // namespace zen