public boolean equalsBytes(@NotNull Bytes b2, long remaining) {
   long i = 0;
   try {
     for (; i < remaining - 7; i++)
       if (readLong(readPosition() + i) != b2.readLong(b2.readPosition() + i)) return false;
     for (; i < remaining; i++)
       if (readByte(readPosition() + i) != b2.readByte(b2.readPosition() + i)) return false;
   } catch (BufferUnderflowException | IORuntimeException e) {
     throw Jvm.rethrow(e);
   }
   return true;
 }
  /**
   * Creates a string from the {@code position} to the {@code limit}, The buffer is not modified by
   * this call
   *
   * @param buffer the buffer to use
   * @return a string contain the text from the {@code position} to the {@code limit}
   */
  static String toString(@NotNull final Bytes<?> buffer) throws BufferUnderflowException {
    if (buffer.readRemaining() == 0) return "";
    return buffer.parseWithLength(
        buffer.readRemaining(),
        b -> {
          final StringBuilder builder = new StringBuilder();
          try {
            while (buffer.readRemaining() > 0) {
              builder.append((char) buffer.readByte());
            }
          } catch (IORuntimeException e) {
            builder.append(' ').append(e);
          }

          // remove the last comma
          return builder.toString();
        });
  }
  /**
   * The buffer is not modified by this call
   *
   * @param buffer the buffer to use
   * @param position the position to create the string from
   * @param len the number of characters to show in the string
   * @return a string contain the text from offset {@code position}
   */
  static String toString(@NotNull final Bytes buffer, long position, long len)
      throws BufferUnderflowException, IORuntimeException {
    final long pos = buffer.readPosition();
    final long limit = buffer.readLimit();
    buffer.readPosition(position);
    buffer.readLimit(position + len);

    try {

      final StringBuilder builder = new StringBuilder();
      while (buffer.readRemaining() > 0) {
        builder.append((char) buffer.readByte());
      }

      // remove the last comma
      return builder.toString();
    } finally {
      buffer.readLimit(limit);
      buffer.readPosition(pos);
    }
  }
  @NotNull
  static String fromSizePrefixedBlobs(@NotNull Bytes bytes, long position, long length) {
    StringBuilder sb = new StringBuilder();

    final long limit0 = bytes.readLimit();
    final long position0 = bytes.readPosition();
    try {
      bytes.readPosition(position);
      long limit2 = Math.min(limit0, position + length);
      bytes.readLimit(limit2);
      long missing = position + length - limit2;
      while (bytes.readRemaining() >= 4) {
        long header = bytes.readUnsignedInt();
        int len = Wires.lengthOf(header);
        if (len > bytes.readRemaining())
          throw new RuntimeException(
              "Are you sure this was written with writeDocument and has a 4 byte size prefix, "
                  + len
                  + " > "
                  + bytes.readRemaining());
        String type =
            Wires.isData(header)
                ? Wires.isReady(header) ? "!!data" : "!!not-ready-data!"
                : Wires.isReady(header) ? "!!meta-data" : "!!not-ready-meta-data!";
        boolean binary = bytes.readByte(bytes.readPosition()) < ' ';

        sb.append("--- ").append(type).append(binary ? " #binary" : "");
        if (missing > 0) sb.append(" # missing: ").append(missing);
        if (len > bytes.readRemaining())
          sb.append(" # len: ").append(len).append(", remaining: ").append(bytes.readRemaining());
        sb.append("\n");

        Bytes textBytes = bytes;

        if (binary) {
          Bytes bytes2 = Bytes.elasticByteBuffer();
          TextWire textWire = new TextWire(bytes2);
          long readLimit = bytes.readLimit();

          try {
            bytes.readLimit(bytes.readPosition() + len);
            new BinaryWire(bytes).copyTo(textWire);
          } finally {
            bytes.readLimit(readLimit);
          }
          textBytes = bytes2;
          len = (int) textBytes.readRemaining();
        }
        try {
          for (int i = 0; i < len; i++) {
            int ch = textBytes.readUnsignedByte();
            sb.append((char) ch);
          }
        } catch (Exception e) {
          sb.append(" ").append(e);
        }
        if (sb.charAt(sb.length() - 1) != '\n') sb.append('\n');
      }

      return sb.toString();
    } finally {
      bytes.readLimit(limit0);
      bytes.readPosition(position0);
    }
  }