public function diff(Delta $other)
 {
     $delta = new self();
     if ($this->getOperations() === $other->getOperations()) {
         return $delta;
     }
     $strings = array_map(function (OperationCollection $operations) use($other) {
         return implode(array_map(function (OperationInterface $operation) use($operations, $other) {
             if ($operation->getType() === OperationInterface::TYPE_INSERT) {
                 return is_string($operation->getValue()) ? $operation->getValue() : chr(0);
             }
             throw new \RuntimeException(sprintf('diff() called %s non-document', $operations === $other->getOperations() ? 'on' : 'with'));
         }, $operations->toArray()));
     }, [$this->getOperations(), $other->getOperations()]);
     $diffResults = FastDiff::diff($strings[0], $strings[1]);
     $thisIterator = $this->getOperations()->getIterator();
     $otherIterator = $other->getOperations()->getIterator();
     foreach ($diffResults as $diffResult) {
         $length = mb_strlen($diffResult[1]);
         while ($length > 0) {
             $operationLength = 0;
             switch ($diffResult[0]) {
                 case FastDiff::DIFF_INSERT:
                     $operationLength = min($otherIterator->getPeekLength(), $length);
                     $delta->push($otherIterator->next($operationLength));
                     break;
                 case FastDiff::DIFF_DELETE:
                     $operationLength = min($length, $thisIterator->getPeekLength());
                     $thisIterator->next($operationLength);
                     $delta->delete($operationLength);
                     break;
                 case FastDiff::DIFF_EQUAL:
                     $operationLength = min($thisIterator->getPeekLength(), $otherIterator->getPeekLength(), $length);
                     $thisOperation = $thisIterator->next($operationLength);
                     $otherOperation = $otherIterator->next($operationLength);
                     if ($thisOperation->getValue() === $otherOperation->getValue()) {
                         $delta->retain($operationLength, $this->diffAttributes($thisOperation->getAttributes(), $otherOperation->getAttributes()));
                     } else {
                         $delta->push($otherOperation)->delete($operationLength);
                     }
                     break;
             }
             $length -= $operationLength;
         }
     }
     return $delta->chop();
 }