///|
priv struct RevertableIter[T] {
  iter : Iter[T]
  buffer : Array[T]
}

///|
fn[T] RevertableIter::new(iter : Iter[T]) -> RevertableIter[T] {
  { iter, buffer: [] }
}

///|
fn[T] RevertableIter::next(self : RevertableIter[T]) -> T? {
  if self.buffer.pop() is (Some(_) as value) {
    value
  } else {
    self.iter.next()
  }
}

///|
fn[T] RevertableIter::revert(self : RevertableIter[T], value : T) -> Unit {
  self.buffer.push(value)
}

///|
fn[T] RevertableIter::peek(self : RevertableIter[T]) -> T? {
  if self.buffer.last() is (Some(_) as value) {
    return value
  }
  if self.iter.next() is Some(value) {
    self.buffer.push(value)
    return Some(value)
  }
  None
}

///|
fn[T] RevertableIter::is_empty(self : RevertableIter[T]) -> Bool {
  self.peek() is None
}