aboutsummaryrefslogtreecommitdiff
path: root/src/zenstore/referencemetadata.h
blob: 5160bfb8b05bdb8a8562374a9e47993db0f92225 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include <zencore/compositebuffer.h>

ZEN_THIRD_PARTY_INCLUDES_START
#include <gsl/gsl-lite.hpp>
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<typename KeyType, typename AttachmentType>
	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<typename KeyType, typename AttachmentType>
CompositeBuffer
BuildReferenceMetaData(uint32_t						   HeaderMagic,
					   std::span<const KeyType>		   Keys,
					   std::span<const uint32_t>	   AttachmentCounts,
					   std::span<const AttachmentType> Attachments)
{
	uint32_t KeyCount = gsl::narrow<uint32_t>(Keys.size());

	ReferenceMetaDataHeader Header(HeaderMagic, KeyCount, Attachments.size());
	return CompositeBuffer(std::vector<SharedBuffer>{
		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<typename KeyType, typename AttachmentType>
bool
GetAttachmentsFromMetaData(const IoBuffer&													  MetaData,
						   const uint32_t													  ExpectedHeaderMagic,
						   std::function<void(std::span<const KeyType>		  Keys,
											  std::span<const uint32_t>		  AttachmentCounts,
											  std::span<const AttachmentType> 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<KeyType, AttachmentType>(Header->EntryCount, Header->AttachmentCount))
			{
				PayloadView.MidInline(sizeof(ReferenceMetaDataHeader));
				std::span<const KeyType> PayloadKeys = {(const KeyType*)PayloadView.GetData(), Header->EntryCount};
				PayloadView.MidInline(sizeof(KeyType) * Header->EntryCount);
				std::span<const uint32_t> PayloadAttachmentCounts = {(const uint32_t*)PayloadView.GetData(), Header->EntryCount};
				PayloadView.MidInline(sizeof(uint32_t) * Header->EntryCount);
				std::span<const AttachmentType> 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