/**
   * Performs a binary search for {@code value} in the ascending sorted off-heap struct collection
   * using long struct key. in the range specified by fromIndex (inclusive) and toIndex (exclusive).
   * Searching in an unsorted collection has an undefined result. It's also undefined which element
   * is found if there are multiple occurrences of the same element.
   *
   * @param collection the sorted collection to search.
   * @param startIndex the inclusive start index.
   * @param endIndex the exclusive end index.
   * @param value the element to find.
   * @param keyOffset long key field offset within stuct bounds
   * @return the non-negative index of the element, or a negative index which is {@code -index - 1}
   *     where the element would be inserted.
   * @throws IllegalArgumentException {@code if (startIndex < 0 || startIndex > endIndex || endIndex
   *     > collection.size()}
   */
  public static long binarySearchByLongKey(
      OffHeapStructCollection collection,
      long startIndex,
      long endIndex,
      long value,
      int keyOffset) {
    if (startIndex < 0 || startIndex > endIndex || endIndex > collection.size()) {
      throw new IllegalArgumentException(
          "Illegal input, collection size: ["
              + collection.size()
              + "], "
              + "startIndex: ["
              + startIndex
              + "], endIndex: ["
              + endIndex
              + "]");
    }
    long lo = startIndex;
    long hi = endIndex - 1;
    while (lo <= hi) {
      long mid = (lo + hi) >>> 1;
      long midVal = collection.getLong(mid, keyOffset);

      if (midVal < value) {
        lo = mid + 1;
      } else if (midVal > value) {
        hi = mid - 1;
      } else {
        return mid; // value found
      }
    }
    return ~lo; // value not present
  }
 /**
  * Performs a binary search for {@code value} in the ascending sorted off-heap struct collection
  * using int struct key. Returns range of indices having given value or empty range. Searching in
  * an unsorted collection has an undefined result. It's also undefined which element is found if
  * there are multiple occurrences of the same element.
  *
  * @param collection the sorted array to search.
  * @param startIndex the inclusive start index.
  * @param endIndex the exclusive end index.
  * @param value the element to find.
  * @param keyOffset int key field offset within stuct bounds
  * @param out range instance, will be set with start/end indices having given value or with empty
  *     value
  */
 public static void binarySearchRangeByIntKey(
     OffHeapStructCollection collection,
     long startIndex,
     long endIndex,
     long value,
     int keyOffset,
     IndexRange out) {
   long ind = binarySearchByIntKey(collection, startIndex, endIndex, value, keyOffset);
   if (ind < 0) {
     out.setEmpty(ind);
     return;
   }
   long from = ind;
   while (from >= startIndex && value == collection.getInt(from, keyOffset)) {
     from -= 1;
   }
   from += 1;
   long to = ind;
   while (to < endIndex && value == collection.getInt(to, keyOffset)) {
     to += 1;
   }
   to -= 1;
   out.set(from, to);
 }
 /**
  * Performs a binary search for {@code value} in the ascending sorted off-heap struct collection
  * using long struct key. Searching in an unsorted collection has an undefined result. It's also
  * undefined which element is found if there are multiple occurrences of the same element.
  *
  * @param collection the sorted array to search.
  * @param value the element to find.
  * @param keyOffset long key field offset within stuct bounds
  * @return the non-negative index of the element, or a negative index which is {@code -index - 1}
  *     where the element would be inserted.
  */
 public static long binarySearchByLongKey(
     OffHeapStructCollection collection, long value, int keyOffset) {
   return binarySearchByLongKey(collection, 0, collection.size(), value, keyOffset);
 }
 /**
  * Performs a binary search for {@code value} in the ascending sorted off-heap struct collection
  * using int struct key. Returns range of indices having given value or empty range. Searching in
  * an unsorted collection has an undefined result. It's also undefined which element is found if
  * there are multiple occurrences of the same element.
  *
  * @param collection the sorted array to search.
  * @param value the element to find.
  * @param keyOffset int key field offset within stuct bounds
  * @param out range instance, will be set with start/end indices having given value or with empty
  *     value
  */
 public static void binarySearchRangeByIntKey(
     OffHeapStructCollection collection, long value, int keyOffset, IndexRange out) {
   binarySearchRangeByIntKey(collection, 0, collection.size(), value, keyOffset, out);
 }