Skip to content

Commit

Permalink
Eliminate recursion in compression streams writeInternal()
Browse files Browse the repository at this point in the history
This avoids having large stack traces when compressing larger chunks of data
and is easier to maintain with the added comments.
  • Loading branch information
fhanau committed Jul 31, 2024
1 parent 8762c15 commit 939dddd
Showing 1 changed file with 18 additions and 13 deletions.
31 changes: 18 additions & 13 deletions src/workerd/api/streams/compression.c++
Original file line number Diff line number Diff line change
Expand Up @@ -285,24 +285,29 @@ private:
// write without reading, which will continue to fill the internal buffer.
KJ_ASSERT(flush == Z_FINISH || state.template is<Open>());
Context::Result result;
KJ_IF_SOME(exception, kj::runCatchingExceptions([this, flush, &result]() {
result = context.pumpOnce(flush);
})) {
cancelInternal(kj::cp(exception));
return kj::mv(exception);
}

if (result.buffer.size() == 0) {
if (result.success) {
return writeInternal(flush);
while (true) {
KJ_IF_SOME(exception, kj::runCatchingExceptions([this, flush, &result]() {
result = context.pumpOnce(flush);
})) {
cancelInternal(kj::cp(exception));
return kj::mv(exception);
}

if (result.buffer.size() == 0) {
if (result.success) {
// No output produced but input data has been processed based on zlib return code, call
// pumpOnce again.
continue;
}
return maybeFulfillRead();
}
return maybeFulfillRead();
}

if (result.buffer.size() > 0) {
// Output has been produced, copy it to result buffer and continue loop to call pumpOnce
// again.
std::copy(result.buffer.begin(), result.buffer.end(), std::back_inserter(output));
}
return writeInternal(flush);
KJ_UNREACHABLE;
}

// Fulfill as many pending reads as we can from the output buffer.
Expand Down

0 comments on commit 939dddd

Please sign in to comment.