// Streams the diff from |last| to |current| into |changes|, using a top-down approach. // Top-down is parallel and efficiently returns the complete diff, but compared to left-right it's slow to start streaming changes. func orderedSequenceDiffTopDown(last orderedSequence, current orderedSequence, changes chan<- ValueChanged, stopChan <-chan struct{}) bool { var lastHeight, currentHeight int functions.All( func() { lastHeight = newCursorAt(last, emptyKey, false, false).depth() }, func() { currentHeight = newCursorAt(current, emptyKey, false, false).depth() }, ) return orderedSequenceDiffInternalNodes(last, current, changes, stopChan, lastHeight, currentHeight) }
// TODO - something other than the literal edit-distance, which is way too much cpu work for this case - https://github.com/attic-labs/noms/issues/2027 func orderedSequenceDiffInternalNodes(last orderedSequence, current orderedSequence, changes chan<- ValueChanged, stopChan <-chan struct{}, lastHeight, currentHeight int) bool { if lastHeight > currentHeight { lastChild := last.(orderedMetaSequence).getCompositeChildSequence(0, uint64(last.seqLen())).(orderedSequence) return orderedSequenceDiffInternalNodes(lastChild, current, changes, stopChan, lastHeight-1, currentHeight) } if currentHeight > lastHeight { currentChild := current.(orderedMetaSequence).getCompositeChildSequence(0, uint64(current.seqLen())).(orderedSequence) return orderedSequenceDiffInternalNodes(last, currentChild, changes, stopChan, lastHeight, currentHeight-1) } if !isMetaSequence(last) && !isMetaSequence(current) { return orderedSequenceDiffLeftRight(last, current, changes, stopChan) } compareFn := last.getCompareFn(current) initialSplices := calcSplices(uint64(last.seqLen()), uint64(current.seqLen()), DEFAULT_MAX_SPLICE_MATRIX_SIZE, func(i uint64, j uint64) bool { return compareFn(int(i), int(j)) }) for _, splice := range initialSplices { var lastChild, currentChild orderedSequence functions.All( func() { lastChild = last.(orderedMetaSequence).getCompositeChildSequence(splice.SpAt, splice.SpRemoved).(orderedSequence) }, func() { currentChild = current.(orderedMetaSequence).getCompositeChildSequence(splice.SpFrom, splice.SpAdded).(orderedSequence) }, ) if ok := orderedSequenceDiffInternalNodes(lastChild, currentChild, changes, stopChan, lastHeight-1, currentHeight-1); !ok { return false } } return true }