aboutsummaryrefslogtreecommitdiff
path: root/zenhttp/httpshared.cpp
blob: f11f91fae96606ab087fcefeea8eb5aed7256281 (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
110
111
112
113
114
115
116
// Copyright Epic Games, Inc. All Rights Reserved.

#include "httpshared.h"

#include <zencore/compactbinarypackage.h>
#include <zencore/iobuffer.h>
#include <zencore/iohash.h>
#include <zencore/stream.h>

#include <span>
#include <vector>

namespace zen {

std::vector<IoBuffer>
FormatPackageMessage(const CbPackage& Data)
{
	const std::span<const CbAttachment>& Attachments = Data.GetAttachments();

	std::vector<IoBuffer> ResponseBuffers;
	ResponseBuffers.reserve(3 + Attachments.size());  // TODO: may want to use an additional fudge factor here to avoid growing since each
													  // attachment is likely to consist of several buffers

	uint64_t TotalAttachmentsSize = 0;

	// Fixed size header

	CbPackageHeader Hdr{.HeaderMagic = kCbPkgMagic, .AttachmentCount = gsl::narrow<uint32_t>(Attachments.size())};

	ResponseBuffers.push_back(IoBufferBuilder::MakeCloneFromMemory(&Hdr, sizeof Hdr));

	// Attachment metadata array

	IoBuffer AttachmentMetadataBuffer = IoBuffer{sizeof(CbAttachmentEntry) * (Attachments.size() + /* root */ 1)};

	CbAttachmentEntry* AttachmentInfo = reinterpret_cast<CbAttachmentEntry*>(AttachmentMetadataBuffer.MutableData());

	ResponseBuffers.push_back(AttachmentMetadataBuffer);  // Attachment metadata

	// Root object

	IoBuffer RootIoBuffer = Data.GetObject().GetBuffer().AsIoBuffer();
	ResponseBuffers.push_back(RootIoBuffer);  // Root object

	*AttachmentInfo++ = {.AttachmentSize = RootIoBuffer.Size(), .AttachmentHash = Data.GetObjectHash()};

	// Attachment payloads

	for (const CbAttachment& Attachment : Attachments)
	{
		CompressedBuffer AttachmentBuffer = Attachment.AsCompressedBinary();
		CompositeBuffer	 Compressed		  = AttachmentBuffer.GetCompressed();

		*AttachmentInfo++ = {.AttachmentSize = AttachmentBuffer.GetCompressedSize(),
							 .AttachmentHash = IoHash::FromBLAKE3(AttachmentBuffer.GetRawHash())};

		for (const SharedBuffer& Segment : Compressed.GetSegments())
		{
			ResponseBuffers.push_back(Segment.AsIoBuffer());
			TotalAttachmentsSize += Segment.GetSize();
		}
	}

	return std::move(ResponseBuffers);
}

CbPackage
ParsePackageMessage(IoBuffer Payload)
{
	MemoryInStream InStream(Payload);
	BinaryReader   Reader(InStream);

	if (!Payload)
	{
		return {};
	}

	CbPackage Package;

	CbPackageHeader Hdr;
	Reader.Read(&Hdr, sizeof Hdr);

	if (Hdr.HeaderMagic != kCbPkgMagic)
	{
		// report error
		return {};
	}

	uint32_t ChunkCount = Hdr.AttachmentCount + 1;

	std::unique_ptr<CbAttachmentEntry[]> AttachmentEntries{new CbAttachmentEntry[ChunkCount]};

	Reader.Read(AttachmentEntries.get(), sizeof(CbAttachmentEntry) * ChunkCount);

	for (uint32_t i = 0; i < ChunkCount; ++i)
	{
		const uint64_t AttachmentSize = AttachmentEntries[i].AttachmentSize;
		IoBuffer	   AttachmentBuffer{AttachmentSize};
		Reader.Read(AttachmentBuffer.MutableData(), AttachmentSize);
		CompressedBuffer CompBuf(CompressedBuffer::FromCompressed(SharedBuffer(AttachmentBuffer)));

		if (i == 0)
		{
			Package.SetObject(LoadCompactBinaryObject(CompBuf));
		}
		else
		{
			CbAttachment Attachment(CompBuf);
			Package.AddAttachment(Attachment);
		}
	}

	return Package;
}

}  // namespace zen