int ZLib::UncompressAtMostOrAll()

in tensorflow_serving/util/net_http/compression/gzip_zlib.cc [553:677]


int ZLib::UncompressAtMostOrAll(Bytef *dest, uLongf *destLen,
                                const Bytef *source, uLong *sourceLen,
                                int flush_mode) {  // Z_SYNC_FLUSH or Z_FINISH
  int err = Z_OK;

  if (first_chunk_) {
    gzip_footer_bytes_ = -1;

    // If we haven't read our first chunk of actual compressed data,
    // and we're expecting gzip headers, then parse some more bytes
    // from the gzip headers.
    const Bytef *bodyBegin = nullptr;
    GZipHeader::Status status = gzip_header_->ReadMore(
        reinterpret_cast<const char *>(source), *sourceLen,
        reinterpret_cast<const char **>(&bodyBegin));
    switch (status) {
      case GZipHeader::INCOMPLETE_HEADER:  // don't have the complete header
        *destLen = 0;
        *sourceLen = 0;  // GZipHeader used all the input
        return Z_OK;
      case GZipHeader::INVALID_HEADER:  // bogus header
        Reset();
        return Z_DATA_ERROR;
      case GZipHeader::COMPLETE_HEADER:      // we have the full header
        *sourceLen -= (bodyBegin - source);  // skip past header bytes
        source = bodyBegin;
        crc_ = crc32(0, nullptr, 0);  // initialize CRC
        break;
      default:
        NET_LOG(FATAL, "Unexpected gzip header parsing result: %d", status);
    }
  } else if (gzip_footer_bytes_ >= 0) {
    // We're now just reading the gzip footer. We already read all the data.
    if (gzip_footer_bytes_ + *sourceLen > sizeof(gzip_footer_)) {
      Reset();
      return Z_DATA_ERROR;
    }
    uLong len = sizeof(gzip_footer_) - gzip_footer_bytes_;
    if (len > *sourceLen) len = *sourceLen;
    if (len > 0) {
      memcpy(gzip_footer_ + gzip_footer_bytes_, source, len);
      gzip_footer_bytes_ += len;
    }
    *sourceLen -= len;
    *destLen = 0;
    return Z_OK;
  }

  if ((err = UncompressInit(dest, destLen, source, sourceLen)) != Z_OK) {
    NET_LOG(WARNING,
            "UncompressInit: Error: %d "
            " SourceLen: %zu",
            err, *sourceLen);
    return err;
  }

  // This is used to figure out how many output bytes we wrote *this chunk*:
  const uLong old_total_out = uncomp_stream_.total_out;

  // This is used to figure out how many input bytes we read *this chunk*:
  const uLong old_total_in = uncomp_stream_.total_in;

  if (first_chunk_) {
    first_chunk_ = false;  // so we don't do this again

    // For the first chunk *only* (to avoid infinite troubles), we let
    // there be no actual data to uncompress.  This sometimes triggers
    // when the input is only the gzip header.
    if (*sourceLen == 0) {
      *destLen = 0;
      return Z_OK;
    }
  }

  // We'll uncompress as much as we can.  If we end OK great, otherwise
  // if we get an error that seems to be the gzip footer, we store the
  // gzip footer and return OK, otherwise we return the error.

  // flush_mode is Z_SYNC_FLUSH for chunked mode, Z_FINISH for all mode.
  err = inflate(&uncomp_stream_, flush_mode);

  // Figure out how many bytes of the input zlib slurped up:
  const uLong bytes_read = uncomp_stream_.total_in - old_total_in;
  assert((source + bytes_read) <= (source + *sourceLen));
  *sourceLen = uncomp_stream_.avail_in;

  // Next we look at the footer, if any. Note that we might currently
  // have just part of the footer (eg, if this data is arriving over a
  // socket). After looking for a footer, log a warning if there is data.
  if ((err == Z_STREAM_END) &&
      ((gzip_footer_bytes_ == -1) ||
       (static_cast<size_t>(gzip_footer_bytes_) < sizeof(gzip_footer_))) &&
      (uncomp_stream_.avail_in <= sizeof(gzip_footer_))) {
    // Store gzip footer bytes so we can check for footer consistency
    // in UncompressChunkDone(). (If we have the whole footer, we
    // could do the checking here, but we don't to keep consistency
    // with CompressChunkDone().)
    gzip_footer_bytes_ =
        std::min(absl::implicit_cast<size_t>(uncomp_stream_.avail_in),
                 sizeof(gzip_footer_));
    memcpy(gzip_footer_, source + bytes_read, gzip_footer_bytes_);
    *sourceLen -= gzip_footer_bytes_;
  } else if ((err == Z_STREAM_END || err == Z_OK)  // everything went ok
             && uncomp_stream_.avail_in == 0) {    // and we read it all
  } else if (err == Z_STREAM_END && uncomp_stream_.avail_in > 0) {
    UncompressErrorInit();
    return Z_DATA_ERROR;
  } else if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) {
    UncompressErrorInit();
    return err;
  } else if (uncomp_stream_.avail_out == 0) {
    err = Z_BUF_ERROR;
  }

  assert(err == Z_OK || err == Z_BUF_ERROR || err == Z_STREAM_END);
  if (err == Z_STREAM_END && !settings_.dont_hide_zstream_end_) err = Z_OK;

  // update the crc and other metadata
  uncompressed_size_ = uncomp_stream_.total_out;
  *destLen = uncomp_stream_.total_out - old_total_out;  // size for this call

  crc_ = crc32(crc_, dest, *destLen);

  return err;
}