bool StreamCodec::compressStream()

in folly/compression/Compression.cpp [235:295]


bool StreamCodec::compressStream(
    ByteRange& input, MutableByteRange& output, StreamCodec::FlushOp flushOp) {
  if (state_ == State::RESET && input.empty() &&
      flushOp == StreamCodec::FlushOp::END &&
      uncompressedLength().value_or(0) != 0) {
    throw std::runtime_error("Codec: invalid uncompressed length");
  }

  if (!uncompressedLength() && needsDataLength()) {
    throw std::runtime_error("Codec: uncompressed length required");
  }
  if (state_ == State::RESET && !input.empty() &&
      uncompressedLength() == uint64_t(0)) {
    throw std::runtime_error("Codec: invalid uncompressed length");
  }
  // Handle input state transitions
  switch (flushOp) {
    case StreamCodec::FlushOp::NONE:
      if (state_ == State::RESET) {
        state_ = State::COMPRESS;
      }
      assertStateIs(State::COMPRESS);
      break;
    case StreamCodec::FlushOp::FLUSH:
      if (state_ == State::RESET || state_ == State::COMPRESS) {
        state_ = State::COMPRESS_FLUSH;
      }
      assertStateIs(State::COMPRESS_FLUSH);
      break;
    case StreamCodec::FlushOp::END:
      if (state_ == State::RESET || state_ == State::COMPRESS) {
        state_ = State::COMPRESS_END;
      }
      assertStateIs(State::COMPRESS_END);
      break;
  }
  size_t const inputSize = input.size();
  size_t const outputSize = output.size();
  bool const done = doCompressStream(input, output, flushOp);
  if (!done && inputSize == input.size() && outputSize == output.size()) {
    if (!progressMade_) {
      throw std::runtime_error("Codec: No forward progress made");
    }
    // Throw an exception if there is no progress again next time
    progressMade_ = false;
  } else {
    progressMade_ = true;
  }
  // Handle output state transitions
  if (done) {
    if (state_ == State::COMPRESS_FLUSH) {
      state_ = State::COMPRESS;
    } else if (state_ == State::COMPRESS_END) {
      state_ = State::END;
    }
    // Check internal invariants
    DCHECK(input.empty());
    DCHECK(flushOp != StreamCodec::FlushOp::NONE);
  }
  return done;
}