docs: private boolean readRequiredBytes() {
      int totalBytesRead = 0;
      int deflatedBytesRead = 0;
      try {
        if (nextFrame == null) {
          nextFrame = new CompositeReadableBuffer();
        }
  
        // Read until the buffer contains all the required bytes.
        int missingBytes;
        while ((missingBytes = requiredLength - nextFrame.readableBytes()) > 0) {
          if (fullStreamDecompressor != null) {
            try {
              if (inflatedBuffer == null || inflatedIndex == inflatedBuffer.length) {
                inflatedBuffer = new byte[Math.min(missingBytes, MAX_BUFFER_SIZE)];
                inflatedIndex = 0;
              }
              int bytesToRead = Math.min(missingBytes, inflatedBuffer.length - inflatedIndex);
              int n = fullStreamDecompressor.inflateBytes(inflatedBuffer, inflatedIndex, bytesToRead);
              totalBytesRead += fullStreamDecompressor.getAndResetBytesConsumed();
              deflatedBytesRead += fullStreamDecompressor.getAndResetDeflatedBytesConsumed();
              if (n == 0) {
                // No more inflated data is available.
                return false;
              }
              nextFrame.addBuffer(ReadableBuffers.wrap(inflatedBuffer, inflatedIndex, n));
              inflatedIndex += n;
            } catch (IOException e) {
              throw new RuntimeException(e);
            } catch (DataFormatException e) {
              throw new RuntimeException(e);
            }
          } else {
            if (unprocessed.readableBytes() == 0) {
              // No more data is available.
              return false;
            }
            int toRead = Math.min(missingBytes, unprocessed.readableBytes());
            totalBytesRead += toRead;
            nextFrame.addBuffer(unprocessed.readBytes(toRead));
          }
        }
        return true;
      } finally {
        if (totalBytesRead > 0) {
          listener.bytesRead(totalBytesRead);
          if (state == State.BODY) {
            if (fullStreamDecompressor != null) {
              // With compressed streams, totalBytesRead can include gzip header and trailer metadata
              statsTraceCtx.inboundWireSize(deflatedBytesRead);
              inboundBodyWireSize += deflatedBytesRead;
            } else {
              statsTraceCtx.inboundWireSize(totalBytesRead);
              inboundBodyWireSize += totalBytesRead;
            }
          }
        }
      }
    }