code: public static int shuffle(ByteBuffer input, BitShuffleType type, ByteBuffer shuffled) throws IOException {
          if (!input.isDirect()) {
              throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
          }
          if (!shuffled.isDirect()) {
              throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "destination is not a direct buffer");
          }
  
          // input: input[pos(), limit())
          // output: shuffled
          int uPos = input.position();
          int uLen = input.remaining();
          int typeSize = type.getTypeSize();
          if (uLen % typeSize != 0) {
              throw new IllegalArgumentException("input length must be a multiple of the given type size: " + typeSize);
          }
          if (shuffled.remaining() < uLen) {
              throw new IllegalArgumentException("not enough space for output");
          }
          int numProcessed = impl.shuffleDirectBuffer(input, uPos, typeSize, uLen, shuffled, shuffled.position());
          assert(numProcessed == uLen);
  
          //         pos   limit
          // [ ......BBBBBBB.........]
          shuffled.limit(shuffled.position() + numProcessed);
          return numProcessed;
      }
docs: Apply a bit-shuffling filter into the content in the given input buffer. After bit-shuffling,
  you can retrieve the shuffled data from the output buffer [pos() ...limit())
  (shuffled data size = limit() - pos() = remaining()).
  
  @param input buffer[pos() ... limit()) containing the input data
  @param type element type of the input data
  @param shuffled output of the shuffled data. Uses range [pos()..].
  @return byte size of the shuffled data.
  @throws SnappyError when the input is not a direct buffer
  @throws IllegalArgumentException when the input length is not a multiple of the given type size