docs: private void deliver() {
      // We can have reentrancy here when using a direct executor, triggered by calls to
      // request more messages. This is safe as we simply loop until pendingDelivers = 0
      if (inDelivery) {
        return;
      }
      inDelivery = true;
      try {
        // Process the uncompressed bytes.
        while (!stopDelivery && pendingDeliveries > 0 && readRequiredBytes()) {
          switch (state) {
            case HEADER:
              processHeader();
              break;
            case BODY:
              // Read the body and deliver the message.
              processBody();
  
              // Since we've delivered a message, decrement the number of pending
              // deliveries remaining.
              pendingDeliveries--;
              break;
            default:
              throw new AssertionError("Invalid state: " + state);
          }
        }
  
        if (stopDelivery) {
          close();
          return;
        }
  
        /*
         * We are stalled when there are no more bytes to process. This allows delivering errors as
         * soon as the buffered input has been consumed, independent of whether the application
         * has requested another message.  At this point in the function, either all frames have been
         * delivered, or unprocessed is empty.  If there is a partial message, it will be inside next
         * frame and not in unprocessed.  If there is extra data but no pending deliveries, it will
         * be in unprocessed.
         */
        if (closeWhenComplete && isStalled()) {
          close();
        }
      } finally {
        inDelivery = false;
      }
    }