///|
/// Invalid positions or failed operations in a requested history.
pub(all) enum JournalRangeError {
  InvalidIndex(Int, Int)
  OperationFailed(Int, RoaringError)
}

///|
/// Return one operation by zero-based index.
pub fn RoaringOperationLog::operation_at(
  self : RoaringOperationLog,
  index : Int,
) -> Result[BitmapOperation, JournalRangeError] {
  if index < 0 || index >= self.operations.length() {
    Err(InvalidIndex(index, self.operations.length()))
  } else {
    Ok(self.operations[index].owned_copy())
  }
}

///|
/// Replay exactly the first `count` operations, reporting a zero-based failure index.
pub fn RoaringOperationLog::replay_prefix(
  self : RoaringOperationLog,
  count : Int,
) -> Result[RoaringBitmap, JournalRangeError] {
  if count < 0 || count > self.operations.length() {
    return Err(InvalidIndex(count, self.operations.length()))
  }
  let mut current = self.checkpoint
  for index in 0.. current = next
      Err(error) => return Err(OperationFailed(index, error))
    }
  }
  Ok(current)
}

///|
/// Split a log into its retained prefix and a suffix rebased on the prefix state.
pub fn RoaringOperationLog::split_at(
  self : RoaringOperationLog,
  count : Int,
) -> Result[(RoaringOperationLog, RoaringOperationLog), JournalRangeError] {
  let checkpoint = match self.replay_prefix(count) {
    Ok(bitmap) => bitmap
    Err(error) => return Err(error)
  }
  let prefix_operations : Array[BitmapOperation] = []
  let suffix_operations : Array[BitmapOperation] = []
  for index in 0.. Result[Array[Int], JournalRangeError] {
  let output : Array[Int] = [self.checkpoint.cardinality()]
  let mut current = self.checkpoint
  for index in 0.. {
        current = next
        output.push(current.cardinality())
      }
      Err(error) => return Err(OperationFailed(index, error))
    }
  }
  Ok(output)
}