feat(common): Sd0::Compress, a default Sd0 and room for chunks that don't shrink

Sd0 gets a default constructor and Sd0::Compress(data), the raw sd0 bytes of
some data (what the client reads for UGC files it downloads without 3D
services). FromData compresses into a heap buffer big enough for a chunk that
grows when deflated (it used a 256 KiB stack buffer, so random data failed and
workers carried a large stack frame), and drops a half-written result.

Tests: chunks as the 1.10.64 client inflates them, incompressible data, empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-27 17:46:34 -05:00
parent 36cefc1ede
commit ceec638e52
4 changed files with 90 additions and 1 deletions

View File

@@ -98,17 +98,20 @@ void Sd0::FromData(const uint8_t* data, size_t bufferSize) {
if (bufferSize == 0) return;
m_Chunks.clear();
// Room for a chunk that doesn't compress (zlib makes it slightly bigger), on the heap: this runs on worker threads
std::vector<uint8_t> compressedChunk(ZCompression::GetMaxCompressedLength(MAX_UNCOMPRESSED_CHUNK_SIZE));
while (bufferSize > 0) {
const auto numToCopy = std::min(MAX_UNCOMPRESSED_CHUNK_SIZE, bufferSize);
const auto* startOffset = data + originalBufferSize - bufferSize;
bufferSize -= numToCopy;
std::array<uint8_t, MAX_UNCOMPRESSED_CHUNK_SIZE> compressedChunk;
const auto compressedSize = ZCompression::Compress(
startOffset, numToCopy,
compressedChunk.data(), compressedChunk.size());
if (compressedSize == -1) {
LOG("Failed to compress chunk, aborting");
// Part of the data isn't a usable buffer
m_Chunks.clear();
break;
}
@@ -128,6 +131,15 @@ void Sd0::FromData(const uint8_t* data, size_t bufferSize) {
}
std::string Sd0::Compress(std::string_view data) {
Sd0 sd0;
if (data.empty()) return std::string(SD0_HEADER, 5);
sd0.FromData(reinterpret_cast<const uint8_t*>(data.data()), data.size());
std::string out;
for (const auto& chunk : sd0.GetAsVector()) out.append(reinterpret_cast<const char*>(chunk.data()), chunk.size());
return out;
}
std::string Sd0::GetAsStringUncompressed() const {
std::string toReturn;
bool first = true;