<?php
 namespace MongoDB\Model;
 use Countable;
 use Iterator;
 use IteratorIterator;
 use Traversable;
 use function count;
 use function current;
 use function key;
 use function next;
 use function reset;
 class CachingIterator implements Countable, Iterator {
 private $items = [];
 private $iterator;
 private $iteratorAdvanced = false;
 private $iteratorExhausted = false;
 public function __construct(Traversable $traversable) {
 $this->iterator = new IteratorIterator($traversable);
 $this->iterator->rewind();
 $this->storeCurrentItem();
 }
 public function count() {
 $this->exhaustIterator();
 return count($this->items);
 }
 public function current() {
 return current($this->items);
 }
 public function key() {
 return key($this->items);
 }
 public function next() {
 if (! $this->iteratorExhausted) {
 $this->iteratorAdvanced = true;
 $this->iterator->next();
 $this->storeCurrentItem();
 $this->iteratorExhausted = ! $this->iterator->valid();
 }
 next($this->items);
 }
 public function rewind() {
 if ($this->iteratorAdvanced) {
 $this->exhaustIterator();
 }
 reset($this->items);
 }
 public function valid() {
 return $this->key() !== null;
 }
 private function exhaustIterator() {
 while (! $this->iteratorExhausted) {
 $this->next();
 }
 }
 private function storeCurrentItem() {
 $key = $this->iterator->key();
 if ($key === null) {
 return;
 }
 $this->items[$key] = $this->iterator->current();
 }
 }
 