/** Recycle this <code>InputBuffer</code> for reuse. */
  public void recycle() {

    inputContentBuffer.tryDispose();
    inputContentBuffer = null;

    singleCharBuf.position(singleCharBuf.limit());

    connection = null;
    decoder = null;
    ctx = null;
    handler = null;

    processingChars = false;
    closed = false;
    contentRead = false;

    markPos = -1;
    readAheadLimit = -1;
    requestedSize = -1;
    readCount = 0;

    averageCharsPerByte = 1.0f;

    isWaitingDataAsynchronously = false;

    encoding = DEFAULT_HTTP_CHARACTER_ENCODING;
  }
  protected void updateInputContentBuffer(final Buffer buffer) {

    buffer.allowBufferDispose(true);

    if (inputContentBuffer == null) {
      inputContentBuffer = buffer;
    } else if (inputContentBuffer.hasRemaining()
        || readAheadLimit
            > 0) { // if the stream is marked - we can't dispose the inputContentBuffer, even if
      // it's been read off
      toCompositeInputContentBuffer().append(buffer);
    } else {
      inputContentBuffer.tryDispose();
      inputContentBuffer = buffer;
    }
  }
  @Override
  public HttpContent encode(Connection connection, HttpContent httpContent) {

    final HttpHeader httpHeader = httpContent.getHttpHeader();
    final Buffer input = httpContent.getContent();

    if (httpContent.isLast() && !input.hasRemaining()) {
      return httpContent;
    }

    final TransformationResult<Buffer, Buffer> result =
        encoder.transform(httpContent.getHttpHeader(), input);

    input.tryDispose();

    try {
      switch (result.getStatus()) {
        case COMPLETE:
          encoder.finish(httpHeader);
        case INCOMPLETE:
          {
            Buffer encodedBuffer = result.getMessage();
            if (encodedBuffer != null) {
              httpContent.setContent(encodedBuffer);
              return httpContent;
            } else {
              return null;
            }
          }

        case ERROR:
          {
            throw new IllegalStateException(
                "LZMA encode error. Code: "
                    + result.getErrorCode()
                    + " Description: "
                    + result.getErrorDescription());
          }

        default:
          throw new IllegalStateException("Unexpected status: " + result.getStatus());
      }
    } finally {
      result.recycle();
    }
  }
  @Override
  public ParsingResult decode(Connection connection, HttpContent httpContent) {
    final HttpHeader httpHeader = httpContent.getHttpHeader();
    final Buffer input = httpContent.getContent();
    final TransformationResult<Buffer, Buffer> result = decoder.transform(httpHeader, input);

    Buffer remainder = result.getExternalRemainder();

    if (remainder == null || !remainder.hasRemaining()) {
      input.tryDispose();
      remainder = null;
    } else {
      input.shrink();
    }

    try {
      switch (result.getStatus()) {
        case COMPLETE:
          {
            httpContent.setContent(result.getMessage());
            decoder.finish(httpHeader);
            return ParsingResult.create(httpContent, remainder);
          }

        case INCOMPLETE:
          {
            return ParsingResult.create(null, remainder);
          }

        case ERROR:
          {
            throw new IllegalStateException(
                "LZMA decode error. Code: "
                    + result.getErrorCode()
                    + " Description: "
                    + result.getErrorDescription());
          }

        default:
          throw new IllegalStateException("Unexpected status: " + result.getStatus());
      }
    } finally {
      result.recycle();
    }
  }