public int readInternal(byte[] b, int offset, int len) {
    if (position >= length) return -1;
    int argPos = offset, argEnd = offset + len;
    while (argPos < argEnd) {
      if (bufferIx == cacheData.length) return (argPos - offset);
      ByteBuffer data = cacheData[bufferIx].getByteBufferDup();
      int toConsume = Math.min(argEnd - argPos, data.remaining() - bufferPos);
      data.position(data.position() + bufferPos);
      data.get(b, argPos, toConsume);
      if (data.remaining() == 0) {
        ++bufferIx;
        bufferPos = 0;
      } else {
        bufferPos += toConsume;
      }
      argPos += toConsume;
    }
    return len;
  }
The Parquet InputFile implementation that allows the reader to
read the footer from cache without being aware of the latter.
This implements both InputFile and the InputStream that the reader gets from InputFile.
ql/src/java/org/apache/hadoop/hive/ql/io/parquet/vector/ParquetFooterInputFromCache.java