mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-27 03:09:14 -06:00
sequences return a compare func used for diffs (#1771)
This commit is contained in:
@@ -18,8 +18,11 @@ func (bl blobLeafSequence) getOffset(idx int) uint64 {
|
||||
return uint64(idx)
|
||||
}
|
||||
|
||||
func (bl blobLeafSequence) equalsAt(idx int, other interface{}) bool {
|
||||
return bl.data[idx] == other
|
||||
func (bl blobLeafSequence) getCompareFn(other sequence) compareFn {
|
||||
otherbl := other.(blobLeafSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
return bl.data[idx] == otherbl.data[otherIdx]
|
||||
}
|
||||
}
|
||||
|
||||
// sequence interface
|
||||
|
||||
@@ -42,8 +42,9 @@ func indexedSequenceDiff(last indexedSequence, lastHeight int, lastOffset uint64
|
||||
return indexedSequenceDiff(last, lastHeight, lastOffset, currentChild, currentHeight-1, currentOffset, newLoadLimit)
|
||||
}
|
||||
|
||||
compareFn := last.getCompareFn(current)
|
||||
initialSplices := calcSplices(uint64(last.seqLen()), uint64(current.seqLen()), func(i uint64, j uint64) bool {
|
||||
return last.equalsAt(int(i), current.getItem(int(j)))
|
||||
return compareFn(int(i), int(j))
|
||||
})
|
||||
|
||||
finalSplices := []Splice{}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
type indexedSequence interface {
|
||||
sequence
|
||||
getOffset(idx int) uint64
|
||||
equalsAt(idx int, other interface{}) bool
|
||||
}
|
||||
|
||||
type indexedMetaSequence struct {
|
||||
@@ -43,16 +42,13 @@ func newIndexedMetaSequence(tuples metaSequenceData, t *Type, vr ValueReader) in
|
||||
cum += mt.uint64Value()
|
||||
offsets = append(offsets, cum)
|
||||
}
|
||||
leafCount := offsets[len(offsets)-1]
|
||||
return indexedMetaSequence{
|
||||
metaSequenceObject{tuples, t, vr},
|
||||
metaSequenceObject{tuples, t, vr, leafCount},
|
||||
offsets,
|
||||
}
|
||||
}
|
||||
|
||||
func (ims indexedMetaSequence) numLeaves() uint64 {
|
||||
return ims.offsets[len(ims.offsets)-1]
|
||||
}
|
||||
|
||||
func (ims indexedMetaSequence) getOffset(idx int) uint64 {
|
||||
// TODO: precompute these on the construction
|
||||
offsets := []uint64{}
|
||||
@@ -65,8 +61,11 @@ func (ims indexedMetaSequence) getOffset(idx int) uint64 {
|
||||
return ims.offsets[idx] - 1
|
||||
}
|
||||
|
||||
func (ims indexedMetaSequence) equalsAt(idx int, other interface{}) bool {
|
||||
return ims.getItem(idx).(metaTuple).ref.Equals(other.(metaTuple).ref)
|
||||
func (ims indexedMetaSequence) getCompareFn(other sequence) compareFn {
|
||||
oms := other.(indexedMetaSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
return ims.tuples[idx].ref.TargetHash() == oms.tuples[otherIdx].ref.TargetHash()
|
||||
}
|
||||
}
|
||||
|
||||
func newCursorAtIndex(seq indexedSequence, idx uint64) *sequenceCursor {
|
||||
|
||||
@@ -24,8 +24,11 @@ func (ll listLeafSequence) getOffset(idx int) uint64 {
|
||||
return uint64(idx)
|
||||
}
|
||||
|
||||
func (ll listLeafSequence) equalsAt(idx int, other interface{}) bool {
|
||||
return ll.values[idx].Equals(other.(Value))
|
||||
func (ll listLeafSequence) getCompareFn(other sequence) compareFn {
|
||||
oll := other.(listLeafSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
return ll.values[idx].Equals(oll.values[otherIdx])
|
||||
}
|
||||
}
|
||||
|
||||
// sequence interface
|
||||
|
||||
@@ -79,10 +79,13 @@ func (ml mapLeafSequence) getKey(idx int) Value {
|
||||
return ml.data[idx].key
|
||||
}
|
||||
|
||||
func (ml mapLeafSequence) equalsAt(idx int, other interface{}) bool {
|
||||
entry := ml.data[idx]
|
||||
otherEntry := other.(mapEntry)
|
||||
return entry.key.Equals(otherEntry.key) && entry.value.Equals(otherEntry.value)
|
||||
func (ml mapLeafSequence) getCompareFn(other sequence) compareFn {
|
||||
oml := other.(mapLeafSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
entry := ml.data[idx]
|
||||
otherEntry := oml.data[otherIdx]
|
||||
return entry.key.Equals(otherEntry.key) && entry.value.Equals(otherEntry.value)
|
||||
}
|
||||
}
|
||||
|
||||
// Collection interface
|
||||
|
||||
@@ -56,9 +56,10 @@ func (msd metaSequenceData) last() metaTuple {
|
||||
}
|
||||
|
||||
type metaSequenceObject struct {
|
||||
tuples metaSequenceData
|
||||
t *Type
|
||||
vr ValueReader
|
||||
tuples metaSequenceData
|
||||
t *Type
|
||||
vr ValueReader
|
||||
leafCount uint64
|
||||
}
|
||||
|
||||
func (ms metaSequenceObject) data() metaSequenceData {
|
||||
@@ -90,6 +91,10 @@ func (ms metaSequenceObject) Type() *Type {
|
||||
return ms.t
|
||||
}
|
||||
|
||||
func (ms metaSequenceObject) numLeaves() uint64 {
|
||||
return ms.leafCount
|
||||
}
|
||||
|
||||
// metaSequence interface
|
||||
func (ms metaSequenceObject) getChildSequence(idx int) sequence {
|
||||
mt := ms.tuples[idx]
|
||||
|
||||
@@ -15,12 +15,10 @@ import (
|
||||
type orderedSequence interface {
|
||||
sequence
|
||||
getKey(idx int) Value
|
||||
equalsAt(idx int, other interface{}) bool
|
||||
}
|
||||
|
||||
type orderedMetaSequence struct {
|
||||
metaSequenceObject
|
||||
leafCount uint64
|
||||
}
|
||||
|
||||
func newSetMetaSequence(tuples metaSequenceData, vr ValueReader) orderedMetaSequence {
|
||||
@@ -53,21 +51,19 @@ func newOrderedMetaSequence(tuples metaSequenceData, t *Type, vr ValueReader) or
|
||||
}
|
||||
|
||||
return orderedMetaSequence{
|
||||
metaSequenceObject{tuples, t, vr},
|
||||
leafCount,
|
||||
metaSequenceObject{tuples, t, vr, leafCount},
|
||||
}
|
||||
}
|
||||
|
||||
func (oms orderedMetaSequence) numLeaves() uint64 {
|
||||
return oms.leafCount
|
||||
}
|
||||
|
||||
func (oms orderedMetaSequence) getKey(idx int) Value {
|
||||
return oms.tuples[idx].value
|
||||
}
|
||||
|
||||
func (oms orderedMetaSequence) equalsAt(idx int, other interface{}) bool {
|
||||
return oms.tuples[idx].ref.Equals(other.(metaTuple).ref)
|
||||
func (oms orderedMetaSequence) getCompareFn(other sequence) compareFn {
|
||||
ooms := other.(orderedMetaSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
return oms.tuples[idx].ref.TargetHash() == ooms.tuples[otherIdx].ref.TargetHash()
|
||||
}
|
||||
}
|
||||
|
||||
func newCursorAtKey(seq orderedSequence, key Value, forInsertion bool, last bool) *sequenceCursor {
|
||||
|
||||
@@ -22,7 +22,7 @@ func orderedSequenceDiff(last orderedSequence, current orderedSequence) (added [
|
||||
fastForward(lastCur, currentCur)
|
||||
|
||||
for lastCur.valid() && currentCur.valid() &&
|
||||
!lastCur.seq.(orderedSequence).equalsAt(lastCur.idx, currentCur.current()) {
|
||||
!lastCur.seq.getCompareFn(currentCur.seq)(lastCur.idx, currentCur.idx) {
|
||||
lastKey := getCurrentKey(lastCur)
|
||||
currentKey := getCurrentKey(currentCur)
|
||||
if lastKey.Equals(currentKey) {
|
||||
@@ -96,6 +96,5 @@ func doFastForward(allowPastEnd bool, a *sequenceCursor, b *sequenceCursor) (aHa
|
||||
}
|
||||
|
||||
func isCurrentEqual(a *sequenceCursor, b *sequenceCursor) bool {
|
||||
aSeq := a.seq.(orderedSequence)
|
||||
return aSeq.equalsAt(a.idx, b.current())
|
||||
return a.seq.getCompareFn(b.seq)(a.idx, b.idx)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ package types
|
||||
|
||||
type sequenceItem interface{}
|
||||
|
||||
type compareFn func(x int, y int) bool
|
||||
|
||||
type sequence interface {
|
||||
getItem(idx int) sequenceItem
|
||||
seqLen() int
|
||||
@@ -13,4 +15,5 @@ type sequence interface {
|
||||
valueReader() ValueReader
|
||||
Chunks() []Ref
|
||||
Type() *Type
|
||||
getCompareFn(other sequence) compareFn
|
||||
}
|
||||
|
||||
@@ -28,6 +28,13 @@ func (ts testSequence) numLeaves() uint64 {
|
||||
return uint64(len(ts.items))
|
||||
}
|
||||
|
||||
func (ts testSequence) getCompareFn(other sequence) compareFn {
|
||||
obl := other.(testSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
return ts.items[idx] == obl.items[otherIdx]
|
||||
}
|
||||
}
|
||||
|
||||
func (ts testSequence) valueReader() ValueReader {
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
@@ -52,7 +52,10 @@ func (sl setLeafSequence) getKey(idx int) Value {
|
||||
return sl.data[idx]
|
||||
}
|
||||
|
||||
func (sl setLeafSequence) equalsAt(idx int, other interface{}) bool {
|
||||
entry := sl.data[idx]
|
||||
return entry.Equals(other.(Value))
|
||||
func (sl setLeafSequence) getCompareFn(other sequence) compareFn {
|
||||
osl := other.(setLeafSequence)
|
||||
return func(idx, otherIdx int) bool {
|
||||
entry := sl.data[idx]
|
||||
return entry.Equals(osl.data[otherIdx])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import Ref from './ref.js';
|
||||
import SequenceChunker from './sequence-chunker.js';
|
||||
import type {BoundaryChecker, makeChunkFn} from './sequence-chunker.js';
|
||||
import {Kind} from './noms-kind.js';
|
||||
import type {EqualsFn} from './edit-distance.js';
|
||||
|
||||
export default class Blob extends Collection<IndexedSequence> {
|
||||
constructor(bytes: Uint8Array) {
|
||||
@@ -134,6 +135,11 @@ export class BlobLeafSequence extends IndexedSequence<number> {
|
||||
getOffset(idx: number): number {
|
||||
return idx;
|
||||
}
|
||||
|
||||
getCompareFn(other: IndexedSequence): EqualsFn {
|
||||
return (idx: number, otherIdx: number) =>
|
||||
this.items[idx] === other.items[otherIdx];
|
||||
}
|
||||
}
|
||||
|
||||
const blobWindowSize = 64;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import type {Splice} from './edit-distance.js';
|
||||
import {calcSplices, SPLICE_ADDED, SPLICE_AT, SPLICE_FROM,
|
||||
SPLICE_REMOVED} from './edit-distance.js';
|
||||
import {equals} from './compare.js';
|
||||
import {IndexedMetaSequence} from './meta-sequence.js';
|
||||
import {invariant} from './assert.js';
|
||||
import type {IndexedSequence} from './indexed-sequence.js';
|
||||
@@ -50,9 +49,7 @@ export function diff(last: IndexedSequence, lastHeight: number, lastOffset: numb
|
||||
invariant(last.isMeta === current.isMeta);
|
||||
invariant(lastHeight === currentHeight);
|
||||
|
||||
const splices = calcSplices(last.length, current.length, last.isMeta ?
|
||||
(l, c) => equals(last.items[l].ref, current.items[c].ref) :
|
||||
(l, c) => equals(last.items[l], current.items[c]));
|
||||
const splices = calcSplices(last.length, current.length, last.getCompareFn(current));
|
||||
|
||||
const splicesP = splices.map(splice => {
|
||||
if (!last.isMeta || splice[SPLICE_REMOVED] === 0 || splice[SPLICE_ADDED] === 0) {
|
||||
|
||||
@@ -8,12 +8,20 @@ import {AsyncIterator} from './async-iterator.js';
|
||||
import type {AsyncIteratorResult} from './async-iterator.js';
|
||||
import {notNull} from './assert.js';
|
||||
import Sequence, {search, SequenceCursor} from './sequence.js';
|
||||
import type {EqualsFn} from './edit-distance.js';
|
||||
import {equals} from './compare.js';
|
||||
|
||||
export class IndexedSequence<T> extends Sequence<T> {
|
||||
getOffset(idx: number): number { // eslint-disable-line no-unused-vars
|
||||
throw new Error('override');
|
||||
}
|
||||
|
||||
getCompareFn(other: IndexedSequence): EqualsFn {
|
||||
return (idx: number, otherIdx: number) =>
|
||||
// $FlowIssue
|
||||
equals(this.items[idx], other.items[otherIdx]);
|
||||
}
|
||||
|
||||
async newCursorAt(idx: number): Promise<IndexedSequenceCursor> {
|
||||
let cursor: ?IndexedSequenceCursor = null;
|
||||
let sequence: ?IndexedSequence = this;
|
||||
|
||||
@@ -23,6 +23,7 @@ import {OrderedSequence, OrderedSequenceCursor, OrderedSequenceIterator} from
|
||||
import diff from './ordered-sequence-diff.js';
|
||||
import {ValueBase} from './value.js';
|
||||
import {Kind} from './noms-kind.js';
|
||||
import type {EqualsFn} from './edit-distance.js';
|
||||
|
||||
export type MapEntry<K: Value, V: Value> = [K, V];
|
||||
|
||||
@@ -196,9 +197,10 @@ export class MapLeafSequence<K: Value, V: Value> extends
|
||||
return this.items[idx][KEY];
|
||||
}
|
||||
|
||||
equalsAt(idx: number, other: MapEntry<K, V>): boolean {
|
||||
const entry = this.items[idx];
|
||||
return equals(entry[KEY], other[KEY]) && equals(entry[VALUE], other[VALUE]);
|
||||
getCompareFn(other: OrderedSequence): EqualsFn {
|
||||
return (idx: number, otherIdx: number) =>
|
||||
equals(this.items[idx][KEY], other.items[otherIdx][KEY]) &&
|
||||
equals(this.items[idx][VALUE], other.items[otherIdx][VALUE]);
|
||||
}
|
||||
|
||||
get chunks(): Array<Ref> {
|
||||
|
||||
@@ -23,7 +23,7 @@ import List from './list.js';
|
||||
import Map from './map.js';
|
||||
import Set from './set.js';
|
||||
import Blob from './blob.js';
|
||||
import {equals} from './compare.js';
|
||||
import type {EqualsFn} from './edit-distance.js';
|
||||
|
||||
export type MetaSequence = Sequence<MetaTuple>;
|
||||
|
||||
@@ -145,6 +145,11 @@ export class IndexedMetaSequence extends IndexedSequence<MetaTuple<number>> {
|
||||
getOffset(idx: number): number {
|
||||
return this._offsets[idx] - 1;
|
||||
}
|
||||
|
||||
getCompareFn(other: IndexedSequence): EqualsFn {
|
||||
return (idx: number, otherIdx: number) =>
|
||||
this.items[idx].ref.targetHash.equals(other.items[otherIdx].ref.targetHash);
|
||||
}
|
||||
}
|
||||
|
||||
export function newMapMetaSequence<K: Value>(vr: ?ValueReader,
|
||||
@@ -194,8 +199,9 @@ export class OrderedMetaSequence<K: Value> extends OrderedSequence<K, MetaTuple<
|
||||
return this.items[idx].value;
|
||||
}
|
||||
|
||||
equalsAt(idx: number, other: MetaTuple): boolean {
|
||||
return equals(this.items[idx].ref, other.ref);
|
||||
getCompareFn(other: OrderedSequence): EqualsFn {
|
||||
return (idx: number, otherIdx: number) =>
|
||||
this.items[idx].ref.targetHash.equals(other.items[otherIdx].ref.targetHash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export default async function diff<K: Value, T>(
|
||||
await fastForward(lastCur, currentCur);
|
||||
|
||||
while (lastCur.valid && currentCur.valid &&
|
||||
!lastCur.sequence.equalsAt(lastCur.idx, currentCur.getCurrent())) {
|
||||
!lastCur.sequence.getCompareFn(currentCur.sequence)(lastCur.idx, currentCur.idx)) {
|
||||
const lastKey = lastCur.getCurrentKey(), currentKey = currentCur.getCurrentKey();
|
||||
|
||||
if (equals(lastKey, currentKey)) {
|
||||
@@ -109,5 +109,5 @@ async function doFastForward(allowPastEnd: boolean,
|
||||
}
|
||||
|
||||
function isCurrentEqual(a: SequenceCursor, b: SequenceCursor): boolean {
|
||||
return a.sequence.equalsAt(a.idx, b.getCurrent());
|
||||
return a.sequence.getCompareFn(b.sequence)(a.idx, b.idx);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import type Value from './value.js'; // eslint-disable-line no-unused-vars
|
||||
import {invariant, notNull} from './assert.js';
|
||||
import {compare} from './compare.js';
|
||||
import search from './binary-search.js';
|
||||
import type {EqualsFn} from './edit-distance.js';
|
||||
import Sequence, {SequenceCursor} from './sequence.js';
|
||||
import {ValueBase} from './value.js';
|
||||
|
||||
@@ -47,10 +48,7 @@ export class OrderedSequence<K: Value, T> extends Sequence<T> {
|
||||
throw new Error('override');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the item in this sequence at |idx| is equal to |other|.
|
||||
*/
|
||||
equalsAt(idx: number, other: any): boolean { // eslint-disable-line no-unused-vars
|
||||
getCompareFn(other: OrderedSequence): EqualsFn { // eslint-disable-line no-unused-vars
|
||||
throw new Error('override');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import {sha1Size} from './hash.js';
|
||||
import {removeDuplicateFromOrdered} from './map.js';
|
||||
import {getValueChunks} from './sequence.js';
|
||||
import {Kind} from './noms-kind.js';
|
||||
import type {EqualsFn} from './edit-distance.js';
|
||||
|
||||
const setWindowSize = 1;
|
||||
const setPattern = ((1 << 6) | 0) - 1;
|
||||
@@ -201,8 +202,9 @@ export class SetLeafSequence<K: Value> extends OrderedSequence<K, K> {
|
||||
return this.items[idx];
|
||||
}
|
||||
|
||||
equalsAt(idx: number, other: any): boolean {
|
||||
return equals(this.items[idx], other);
|
||||
getCompareFn(other: OrderedSequence): EqualsFn {
|
||||
return (idx: number, otherIdx: number) =>
|
||||
equals(this.items[idx], other.items[otherIdx]);
|
||||
}
|
||||
|
||||
get chunks(): Array<Ref> {
|
||||
|
||||
Reference in New Issue
Block a user