mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-11 18:49:14 -06:00
Make Map use Array<[K, V]> instead of Array<K | V> (#1538)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@attic/noms",
|
||||
"version": "31.0.0",
|
||||
"version": "32.0.0",
|
||||
"description": "Noms JS SDK",
|
||||
"repository": "https://github.com/attic-labs/noms",
|
||||
"main": "dist/commonjs/noms.js",
|
||||
|
||||
@@ -90,7 +90,7 @@ suite('validate type', () => {
|
||||
|
||||
test('map', async () => {
|
||||
const mapOfNumberToStringType = makeMapType(numberType, stringType);
|
||||
const m = await newMap([0, 'a', 2, 'b']);
|
||||
const m = await newMap([[0, 'a'], [2, 'b']]);
|
||||
assertSubtype(mapOfNumberToStringType, m);
|
||||
assertAll(mapOfNumberToStringType, m);
|
||||
|
||||
@@ -174,7 +174,7 @@ suite('validate type', () => {
|
||||
assertSubtype(mt, await newMap([]));
|
||||
|
||||
// Map<> not a subtype of Map<Number, Number>
|
||||
assertInvalid(makeMapType(makeUnionType([]), makeUnionType([])), await newMap([1, 2]));
|
||||
assertInvalid(makeMapType(makeUnionType([]), makeUnionType([])), await newMap([[1, 2]]));
|
||||
});
|
||||
|
||||
test('struct subtype by name', () => {
|
||||
|
||||
@@ -69,7 +69,7 @@ suite('compare.js', () => {
|
||||
// The order of these are done by the hash.
|
||||
ds.writeValue(10),
|
||||
await newSet([0, 1, 2, 3]),
|
||||
await newMap([0, 1, 2, 3]),
|
||||
await newMap([[0, 1], [2, 3]]),
|
||||
boolType,
|
||||
await newBlob(new Uint8Array([0, 1, 2, 3])),
|
||||
await newList([0, 1, 2, 3]),
|
||||
|
||||
@@ -155,7 +155,7 @@ suite('Database', () => {
|
||||
const commit = await newCommit('foo', []);
|
||||
|
||||
const commitRef = ds.writeValue(commit);
|
||||
const datasets = await newMap(['foo', commitRef]);
|
||||
const datasets = await newMap([['foo', commitRef]]);
|
||||
const rootRef = ds.writeValue(datasets).targetRef;
|
||||
assert.isTrue(await bs.updateRoot(rootRef, emptyRef));
|
||||
ds = new Database(bs); // refresh the datasets
|
||||
|
||||
@@ -213,7 +213,7 @@ suite('Decode', () => {
|
||||
const v: Map<number, number> = r.readValue();
|
||||
invariant(v instanceof Map);
|
||||
|
||||
const m = new Map(newMapLeafSequence(ds, [{key: 0, value: 1}, {key: 2, value: 3}]));
|
||||
const m = new Map(newMapLeafSequence(ds, [[0, 1], [2, 3]]));
|
||||
assert.isTrue(equals(v, m));
|
||||
});
|
||||
|
||||
@@ -231,7 +231,7 @@ suite('Decode', () => {
|
||||
const v: Map<RefValue<Value>, number> = r.readValue();
|
||||
invariant(v instanceof Map);
|
||||
|
||||
const m = new Map(newMapLeafSequence(ds, [{key: rv1, value: 2}, {key: rv2, value: 4}]));
|
||||
const m = new Map(newMapLeafSequence(ds, [[rv1, 2], [rv2, 4]]));
|
||||
assert.isTrue(equals(v, m));
|
||||
});
|
||||
|
||||
@@ -243,7 +243,7 @@ suite('Decode', () => {
|
||||
const v: Map<number, number> = r.readValue();
|
||||
invariant(v instanceof Map);
|
||||
|
||||
const m = new Map(newMapLeafSequence(ds, [{key: 0, value: 1}, {key: 2, value: 3}]));
|
||||
const m = new Map(newMapLeafSequence(ds, [[0, 1], [2, 3]]));
|
||||
assert.isTrue(equals(v, m));
|
||||
});
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ export class JsonArrayReader {
|
||||
while (!this.atEnd()) {
|
||||
const k = this.readValue();
|
||||
const v = this.readValue();
|
||||
entries.push({key: k, value: v});
|
||||
entries.push([k, v]);
|
||||
}
|
||||
|
||||
return new MapLeafSequence(this._ds, t, entries);
|
||||
|
||||
@@ -152,8 +152,7 @@ suite('Encode', () => {
|
||||
const ds = new Database(makeTestingBatchStore());
|
||||
const w = new JsonArrayWriter(ds);
|
||||
|
||||
const v = new Map(newMapLeafSequence(ds, [{key: 'a', value: false},
|
||||
{key:'b', value:true}]));
|
||||
const v = new Map(newMapLeafSequence(ds, [['a', false], ['b', true]]));
|
||||
w.writeValue(v);
|
||||
assert.deepEqual([Kind.Map, Kind.String, Kind.Bool, false,
|
||||
[Kind.String, 'a', Kind.Bool, false, Kind.String, 'b', Kind.Bool, true]], w.array);
|
||||
@@ -165,8 +164,8 @@ suite('Encode', () => {
|
||||
|
||||
// Map<Map<String, Number>, Set<Bool>>({{'a': 0}: {true}})
|
||||
const s = new Set(newSetLeafSequence(ds, [true]));
|
||||
const m1 = new Map(newMapLeafSequence(ds, [{key: 'a', value: 0}]));
|
||||
const v = new Map(newMapLeafSequence(ds, [{key: m1, value: s}]));
|
||||
const m1 = new Map(newMapLeafSequence(ds, [['a', 0]]));
|
||||
const v = new Map(newMapLeafSequence(ds, [[m1, s]]));
|
||||
w.writeValue(v);
|
||||
assert.deepEqual([Kind.Map,
|
||||
Kind.Map, Kind.String, Kind.Number,
|
||||
|
||||
@@ -173,8 +173,8 @@ export class JsonArrayWriter {
|
||||
invariant(sequence instanceof MapLeafSequence);
|
||||
const w2 = new JsonArrayWriter(this._vw);
|
||||
sequence.items.forEach(entry => {
|
||||
w2.writeValue(entry.key);
|
||||
w2.writeValue(entry.value);
|
||||
w2.writeValue(entry[0]);
|
||||
w2.writeValue(entry[1]);
|
||||
});
|
||||
this.write(w2.array);
|
||||
break;
|
||||
|
||||
@@ -41,10 +41,11 @@ suite('BuildMap', () => {
|
||||
|
||||
test('unique keys - strings', async () => {
|
||||
const kvs = [
|
||||
'hello', 'world',
|
||||
'foo', 'bar',
|
||||
'bar', 'foo',
|
||||
'hello', 'foo'];
|
||||
['hello', 'world'],
|
||||
['foo', 'bar'],
|
||||
['bar', 'foo'],
|
||||
['hello', 'foo'],
|
||||
];
|
||||
const m = await newMap(kvs);
|
||||
assert.strictEqual(3, m.size);
|
||||
assert.strictEqual('foo', await m.get('hello'));
|
||||
@@ -52,11 +53,12 @@ suite('BuildMap', () => {
|
||||
|
||||
test('unique keys - number', async () => {
|
||||
const kvs = [
|
||||
4, 1,
|
||||
0, 2,
|
||||
1, 2,
|
||||
3, 4,
|
||||
1, 5];
|
||||
[4, 1],
|
||||
[0, 2],
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
[1, 5],
|
||||
];
|
||||
const m = await newMap(kvs);
|
||||
assert.strictEqual(4, m.size);
|
||||
assert.strictEqual(5, await m.get(1));
|
||||
@@ -65,7 +67,7 @@ suite('BuildMap', () => {
|
||||
test('LONG: set of n numbers', async () => {
|
||||
const kvs = [];
|
||||
for (let i = 0; i < testMapSize; i++) {
|
||||
kvs.push(i, i + 1);
|
||||
kvs.push([i, i + 1]);
|
||||
}
|
||||
|
||||
const m = await newMap(kvs);
|
||||
@@ -91,10 +93,10 @@ suite('BuildMap', () => {
|
||||
test('LONG: map of ref to ref, set of n numbers', async () => {
|
||||
const kvs = [];
|
||||
for (let i = 0; i < testMapSize; i++) {
|
||||
kvs.push(i, i + 1);
|
||||
kvs.push([i, i + 1]);
|
||||
}
|
||||
|
||||
const kvRefs = kvs.map(n => new RefValue(newStruct('num', {n})));
|
||||
const kvRefs = kvs.map(entry => entry.map(n => new RefValue(newStruct('num', {n}))));
|
||||
const m = await newMap(kvRefs);
|
||||
assert.strictEqual(m.ref.toString(), 'sha1-5c9a17f6da0ebfebc1f82f498ac46992fad85250');
|
||||
const height = deriveCollectionHeight(m);
|
||||
@@ -106,7 +108,7 @@ suite('BuildMap', () => {
|
||||
test('LONG: set', async () => {
|
||||
const kvs = [];
|
||||
for (let i = 0; i < testMapSize - 10; i++) {
|
||||
kvs.push(i, i + 1);
|
||||
kvs.push([i, i + 1]);
|
||||
}
|
||||
|
||||
let m = await newMap(kvs);
|
||||
@@ -121,7 +123,7 @@ suite('BuildMap', () => {
|
||||
test('LONG: set existing', async () => {
|
||||
const kvs = [];
|
||||
for (let i = 0; i < testMapSize; i++) {
|
||||
kvs.push(i, i + 1);
|
||||
kvs.push([i, i + 1]);
|
||||
}
|
||||
|
||||
let m = await newMap(kvs);
|
||||
@@ -136,7 +138,7 @@ suite('BuildMap', () => {
|
||||
test('LONG: remove', async () => {
|
||||
const kvs = [];
|
||||
for (let i = 0; i < testMapSize + 10; i++) {
|
||||
kvs.push(i, i + 1);
|
||||
kvs.push([i, i + 1]);
|
||||
}
|
||||
|
||||
let m = await newMap(kvs);
|
||||
@@ -153,7 +155,7 @@ suite('BuildMap', () => {
|
||||
|
||||
const kvs = [];
|
||||
for (let i = 0; i < testMapSize; i++) {
|
||||
kvs.push(i, i + 1);
|
||||
kvs.push([i, i + 1]);
|
||||
}
|
||||
|
||||
const m = await newMap(kvs);
|
||||
@@ -161,15 +163,15 @@ suite('BuildMap', () => {
|
||||
const r = ds.writeValue(m).targetRef;
|
||||
const m2 = await ds.readValue(r);
|
||||
const outKvs = [];
|
||||
await m2.forEach((v, k) => outKvs.push(k, v));
|
||||
await m2.forEach((v, k) => outKvs.push([k, v]));
|
||||
assert.deepEqual(kvs, outKvs);
|
||||
assert.strictEqual(testMapSize, m2.size);
|
||||
|
||||
invariant(m2 instanceof Map);
|
||||
const m3 = await m2.remove(testMapSize - 1);
|
||||
const outKvs2 = [];
|
||||
await m3.forEach((v, k) => outKvs2.push(k, v));
|
||||
kvs.splice(testMapSize * 2 - 2, 2);
|
||||
await m3.forEach((v, k) => outKvs2.push([k, v]));
|
||||
kvs.splice(testMapSize * 1 - 1, 1);
|
||||
assert.deepEqual(kvs, outKvs2);
|
||||
assert.strictEqual(testMapSize - 1, m3.size);
|
||||
});
|
||||
@@ -193,7 +195,7 @@ suite('BuildMap', () => {
|
||||
} else {
|
||||
numbers.push(v);
|
||||
}
|
||||
kvs.push(v, i);
|
||||
kvs.push([v, i]);
|
||||
keys.push(v);
|
||||
}
|
||||
|
||||
@@ -267,7 +269,7 @@ suite('MapLeaf', () => {
|
||||
let m = newMap([]);
|
||||
assert.isTrue(m.isEmpty());
|
||||
assert.strictEqual(0, m.size);
|
||||
m = newMap([{key: 'a', value: false}, {key: 'k', value: true}]);
|
||||
m = newMap([['a', false], ['k', true]]);
|
||||
assert.isFalse(m.isEmpty());
|
||||
assert.strictEqual(2, m.size);
|
||||
});
|
||||
@@ -275,7 +277,7 @@ suite('MapLeaf', () => {
|
||||
test('has', async () => {
|
||||
const ds = new Database(makeTestingBatchStore());
|
||||
const m = new Map(
|
||||
newMapLeafSequence(ds, [{key: 'a', value: false}, {key: 'k', value: true}]));
|
||||
newMapLeafSequence(ds, [['a', false], ['k', true]]));
|
||||
assert.isTrue(await m.has('a'));
|
||||
assert.isFalse(await m.has('b'));
|
||||
assert.isTrue(await m.has('k'));
|
||||
@@ -285,7 +287,7 @@ suite('MapLeaf', () => {
|
||||
test('first/last/get', async () => {
|
||||
const ds = new Database(makeTestingBatchStore());
|
||||
const m = new Map(
|
||||
newMapLeafSequence(ds, [{key: 'a', value: 4}, {key: 'k', value: 8}]));
|
||||
newMapLeafSequence(ds, [['a', 4], ['k', 8]]));
|
||||
|
||||
assert.deepEqual(['a', 4], await m.first());
|
||||
assert.deepEqual(['k', 8], await m.last());
|
||||
@@ -299,7 +301,7 @@ suite('MapLeaf', () => {
|
||||
test('forEach', async () => {
|
||||
const ds = new Database(makeTestingBatchStore());
|
||||
const m = new Map(
|
||||
newMapLeafSequence(ds, [{key: 'a', value: 4}, {key: 'k', value: 8}]));
|
||||
newMapLeafSequence(ds, [['a', 4], ['k', 8]]));
|
||||
|
||||
const kv = [];
|
||||
await m.forEach((v, k) => { kv.push(k, v); });
|
||||
@@ -316,8 +318,8 @@ suite('MapLeaf', () => {
|
||||
};
|
||||
|
||||
await test([]);
|
||||
await test([{key: 'a', value: 4}]);
|
||||
await test([{key: 'a', value: 4}, {key: 'k', value: 8}]);
|
||||
await test([['a', 4]]);
|
||||
await test([['a', 4], ['k', 8]]);
|
||||
});
|
||||
|
||||
test('LONG: iteratorAt', async () => {
|
||||
@@ -327,14 +329,14 @@ suite('MapLeaf', () => {
|
||||
assert.deepEqual([], await flatten(build([]).iteratorAt('a')));
|
||||
|
||||
{
|
||||
const kv = [{key: 'b', value: 5}];
|
||||
const kv = [['b', 5]];
|
||||
assert.deepEqual(kv, await flatten(build(kv).iteratorAt('a')));
|
||||
assert.deepEqual(kv, await flatten(build(kv).iteratorAt('b')));
|
||||
assert.deepEqual([], await flatten(build(kv).iteratorAt('c')));
|
||||
}
|
||||
|
||||
{
|
||||
const kv = [{key: 'b', value: 5}, {key: 'd', value: 10}];
|
||||
const kv = [['b', 5], ['d', 10]];
|
||||
assert.deepEqual(kv, await flatten(build(kv).iteratorAt('a')));
|
||||
assert.deepEqual(kv, await flatten(build(kv).iteratorAt('b')));
|
||||
assert.deepEqual(kv.slice(1), await flatten(build(kv).iteratorAt('c')));
|
||||
@@ -350,7 +352,7 @@ suite('MapLeaf', () => {
|
||||
const r3 = ds.writeValue('b');
|
||||
const r4 = ds.writeValue(false);
|
||||
const m = new Map(
|
||||
newMapLeafSequence(ds, [{key: r1, value: r2}, {key: r3, value: r4}]));
|
||||
newMapLeafSequence(ds, [[r1, r2], [r3, r4]]));
|
||||
assert.strictEqual(4, m.chunks.length);
|
||||
assert.isTrue(equals(r1, m.chunks[0]));
|
||||
assert.isTrue(equals(r2, m.chunks[1]));
|
||||
@@ -362,17 +364,13 @@ suite('MapLeaf', () => {
|
||||
|
||||
suite('CompoundMap', () => {
|
||||
function build(vwr: ValueReadWriter): Array<Map> {
|
||||
const l1 = new Map(newMapLeafSequence(vwr, [{key: 'a', value: false},
|
||||
{key:'b', value:false}]));
|
||||
const l1 = new Map(newMapLeafSequence(vwr, [['a', false], ['b', false]]));
|
||||
const r1 = vwr.writeValue(l1);
|
||||
const l2 = new Map(newMapLeafSequence(vwr, [{key: 'e', value: true},
|
||||
{key:'f', value:true}]));
|
||||
const l2 = new Map(newMapLeafSequence(vwr, [['e', true], ['f', true]]));
|
||||
const r2 = vwr.writeValue(l2);
|
||||
const l3 = new Map(newMapLeafSequence(vwr, [{key: 'h', value: false},
|
||||
{key:'i', value:true}]));
|
||||
const l3 = new Map(newMapLeafSequence(vwr, [['h', false], ['i', true]]));
|
||||
const r3 = vwr.writeValue(l3);
|
||||
const l4 = new Map(newMapLeafSequence(vwr, [{key: 'm', value: true},
|
||||
{key:'n', value:false}]));
|
||||
const l4 = new Map(newMapLeafSequence(vwr, [['m', true], ['n', false]]));
|
||||
const r4 = vwr.writeValue(l4);
|
||||
|
||||
const m1 = new Map(newMapMetaSequence(vwr, [new MetaTuple(r1, 'b', 2),
|
||||
@@ -454,9 +452,8 @@ suite('CompoundMap', () => {
|
||||
test('iterator', async () => {
|
||||
const ds = new Database(makeTestingBatchStore());
|
||||
const [c] = build(ds);
|
||||
const expected = [{key: 'a', value: false}, {key: 'b', value: false}, {key: 'e', value: true},
|
||||
{key: 'f', value: true}, {key: 'h', value: false}, {key: 'i', value: true},
|
||||
{key: 'm', value: true}, {key: 'n', value: false}];
|
||||
const expected = [['a', false], ['b', false], ['e', true], ['f', true], ['h', false],
|
||||
['i', true], ['m', true], ['n', false]];
|
||||
assert.deepEqual(expected, await flatten(c.iterator()));
|
||||
assert.deepEqual(expected, await flattenParallel(c.iterator(), expected.length));
|
||||
});
|
||||
@@ -464,9 +461,8 @@ suite('CompoundMap', () => {
|
||||
test('LONG: iteratorAt', async () => {
|
||||
const ds = new Database(makeTestingBatchStore());
|
||||
const [c] = build(ds);
|
||||
const entries = [{key: 'a', value: false}, {key: 'b', value: false}, {key: 'e', value: true},
|
||||
{key: 'f', value: true}, {key: 'h', value: false}, {key: 'i', value: true},
|
||||
{key: 'm', value: true}, {key: 'n', value: false}];
|
||||
const entries = [['a', false], ['b', false], ['e', true], ['f', true], ['h', false],
|
||||
['i', true], ['m', true], ['n', false]];
|
||||
const offsets = {
|
||||
_: 0, a: 0,
|
||||
b: 1,
|
||||
@@ -496,8 +492,7 @@ suite('CompoundMap', () => {
|
||||
await iter.return();
|
||||
}
|
||||
}
|
||||
assert.deepEqual([{key: 'a', value: false}, {key: 'b', value: false}, {key: 'e', value: true},
|
||||
{key: 'f', value: true}, {key: 'h', value: false}],
|
||||
assert.deepEqual([['a', false], ['b', false], ['e', true], ['f', true], ['h', false]],
|
||||
values);
|
||||
});
|
||||
|
||||
@@ -506,8 +501,8 @@ suite('CompoundMap', () => {
|
||||
const [c] = build(ds);
|
||||
const iter = c.iterator();
|
||||
const values = await Promise.all([iter.next(), iter.next(), iter.return(), iter.next()]);
|
||||
assert.deepEqual([{done: false, value: {key: 'a', value: false}},
|
||||
{done: false, value: {key: 'b', value: false}},
|
||||
assert.deepEqual([{done: false, value: ['a', false]},
|
||||
{done: false, value: ['b', false]},
|
||||
{done: true}, {done: true}],
|
||||
values);
|
||||
});
|
||||
@@ -528,18 +523,18 @@ suite('CompoundMap', () => {
|
||||
for (let i = 0; i < mapSize; i++) {
|
||||
const r = Math.random();
|
||||
if (r <= inM1) {
|
||||
kv1.push(i, i + '');
|
||||
kv1.push([i, i + '']);
|
||||
removed.push(i);
|
||||
} else if (r <= inM1 + inM2) {
|
||||
kv2.push(i, i + '');
|
||||
kv2.push([i, i + '']);
|
||||
added.push(i);
|
||||
} else if (r <= inM1 + inM2 + inBoth) {
|
||||
kv1.push(i, i + '');
|
||||
kv2.push(i, i + '_');
|
||||
kv1.push([i, i + '']);
|
||||
kv2.push([i, i + '_']);
|
||||
modified.push(i);
|
||||
} else {
|
||||
kv1.push(i, i + '');
|
||||
kv2.push(i, i + '');
|
||||
kv1.push([i, i + '']);
|
||||
kv2.push([i, i + '']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ import diff from './ordered-sequence-diff.js';
|
||||
import {Value} from './value.js';
|
||||
import {Kind} from './noms-kind.js';
|
||||
|
||||
export type MapEntry<K: valueOrPrimitive, V: valueOrPrimitive> = {
|
||||
key: K,
|
||||
value: V,
|
||||
};
|
||||
export type MapEntry<K: valueOrPrimitive, V: valueOrPrimitive> = [K, V];
|
||||
|
||||
const KEY = 0;
|
||||
const VALUE = 1;
|
||||
|
||||
const mapWindowSize = 1;
|
||||
const mapPattern = ((1 << 6) | 0) - 1;
|
||||
@@ -33,7 +33,7 @@ function newMapLeafChunkFn<K: valueOrPrimitive, V: valueOrPrimitive>(vr: ?ValueR
|
||||
return (items: Array<MapEntry<K, V>>) => {
|
||||
let indexValue: ?valueOrPrimitive = null;
|
||||
if (items.length > 0) {
|
||||
indexValue = items[items.length - 1].key;
|
||||
indexValue = items[items.length - 1][KEY];
|
||||
if (indexValue instanceof Value) {
|
||||
indexValue = new RefValue(indexValue);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ function newMapLeafChunkFn<K: valueOrPrimitive, V: valueOrPrimitive>(vr: ?ValueR
|
||||
function newMapLeafBoundaryChecker<K: valueOrPrimitive, V: valueOrPrimitive>():
|
||||
BoundaryChecker<MapEntry<K, V>> {
|
||||
return new BuzHashBoundaryChecker(mapWindowSize, sha1Size, mapPattern,
|
||||
(entry: MapEntry<K, V>) => getRefOfValue(entry.key).digest);
|
||||
(entry: MapEntry<K, V>) => getRefOfValue(entry[KEY]).digest);
|
||||
}
|
||||
|
||||
export function removeDuplicateFromOrdered<T>(elems: Array<T>,
|
||||
@@ -69,24 +69,22 @@ export function removeDuplicateFromOrdered<T>(elems: Array<T>,
|
||||
}
|
||||
|
||||
function compareKeys(v1, v2) {
|
||||
return compare(v1.key, v2.key);
|
||||
return compare(v1[KEY], v2[KEY]);
|
||||
}
|
||||
|
||||
function buildMapData<K: valueOrPrimitive, V: valueOrPrimitive>(kvs: Array<K | V>):
|
||||
Array<MapEntry<K, V>> {
|
||||
function buildMapData<K: valueOrPrimitive, V: valueOrPrimitive>(
|
||||
kvs: Array<MapEntry<K, V>>): Array<MapEntry<K, V>> {
|
||||
// TODO: Assert k & v are of correct type
|
||||
const entries = [];
|
||||
for (let i = 0; i < kvs.length; i += 2) {
|
||||
// $FlowIssue: gets confused about the K | V type.
|
||||
const key: K = kvs[i], value: V = kvs[i + 1];
|
||||
entries.push({key, value});
|
||||
for (let i = 0; i < kvs.length; i++) {
|
||||
entries.push([kvs[i][KEY], kvs[i][VALUE]]);
|
||||
}
|
||||
entries.sort(compareKeys);
|
||||
return removeDuplicateFromOrdered(entries, compareKeys);
|
||||
}
|
||||
|
||||
export function newMap<K: valueOrPrimitive, V: valueOrPrimitive>(kvs: Array<K | V>):
|
||||
Promise<Map<K, V>> {
|
||||
export function newMap<K: valueOrPrimitive, V: valueOrPrimitive>(
|
||||
kvs: Array<MapEntry<K, V>>): Promise<Map<K, V>> {
|
||||
return chunkSequence(null, buildMapData(kvs), 0, newMapLeafChunkFn(null),
|
||||
newOrderedMetaSequenceChunkFn(Kind.Map, null),
|
||||
newMapLeafBoundaryChecker(),
|
||||
@@ -100,21 +98,20 @@ export default class Map<K: valueOrPrimitive, V: valueOrPrimitive> extends
|
||||
return cursor.valid && equals(cursor.getCurrentKey(), key);
|
||||
}
|
||||
|
||||
async _firstOrLast(last: boolean): Promise<?[K, V]> {
|
||||
async _firstOrLast(last: boolean): Promise<?MapEntry<K, V>> {
|
||||
const cursor = await this.sequence.newCursorAt(null, false, last);
|
||||
if (!cursor.valid) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const entry = cursor.getCurrent();
|
||||
return [entry.key, entry.value];
|
||||
return cursor.getCurrent();
|
||||
}
|
||||
|
||||
first(): Promise<?[K, V]> {
|
||||
first(): Promise<?MapEntry<K, V>> {
|
||||
return this._firstOrLast(false);
|
||||
}
|
||||
|
||||
last(): Promise<?[K, V]> {
|
||||
last(): Promise<?MapEntry<K, V>> {
|
||||
return this._firstOrLast(true);
|
||||
}
|
||||
|
||||
@@ -125,13 +122,13 @@ export default class Map<K: valueOrPrimitive, V: valueOrPrimitive> extends
|
||||
}
|
||||
|
||||
const entry = cursor.getCurrent();
|
||||
return equals(entry.key, key) ? entry.value : undefined;
|
||||
return equals(entry[KEY], key) ? entry[VALUE] : undefined;
|
||||
}
|
||||
|
||||
async forEach(cb: (v: V, k: K) => void): Promise<void> {
|
||||
const cursor = await this.sequence.newCursorAt(null);
|
||||
return cursor.iter(entry => {
|
||||
cb(entry.value, entry.key);
|
||||
cb(entry[VALUE], entry[KEY]);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
@@ -158,14 +155,14 @@ export default class Map<K: valueOrPrimitive, V: valueOrPrimitive> extends
|
||||
const cursor = await this.sequence.newCursorAt(key, true);
|
||||
if (cursor.valid && equals(cursor.getCurrentKey(), key)) {
|
||||
const entry = cursor.getCurrent();
|
||||
if (equals(entry.value, value)) {
|
||||
if (equals(entry[VALUE], value)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
remove = 1;
|
||||
}
|
||||
|
||||
return this._splice(cursor, [{key: key, value: value}], remove);
|
||||
return this._splice(cursor, [[key, value]], remove);
|
||||
}
|
||||
|
||||
async remove(key: K): Promise<Map<K, V>> {
|
||||
@@ -192,22 +189,22 @@ export default class Map<K: valueOrPrimitive, V: valueOrPrimitive> extends
|
||||
export class MapLeafSequence<K: valueOrPrimitive, V: valueOrPrimitive> extends
|
||||
OrderedSequence<K, MapEntry<K, V>> {
|
||||
getKey(idx: number): K {
|
||||
return this.items[idx].key;
|
||||
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);
|
||||
return equals(entry[KEY], other[KEY]) && equals(entry[VALUE], other[VALUE]);
|
||||
}
|
||||
|
||||
get chunks(): Array<RefValue> {
|
||||
const chunks = [];
|
||||
for (const entry of this.items) {
|
||||
if (entry.key instanceof Value) {
|
||||
chunks.push(...entry.key.chunks);
|
||||
if (entry[KEY] instanceof Value) {
|
||||
chunks.push(...entry[KEY].chunks);
|
||||
}
|
||||
if (entry.value instanceof Value) {
|
||||
chunks.push(...entry.value.chunks);
|
||||
if (entry[VALUE] instanceof Value) {
|
||||
chunks.push(...entry[VALUE].chunks);
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
@@ -219,8 +216,8 @@ export function newMapLeafSequence<K: valueOrPrimitive, V: valueOrPrimitive>(vr:
|
||||
const kt = [];
|
||||
const vt = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
kt.push(getTypeOfValue(items[i].key));
|
||||
vt.push(getTypeOfValue(items[i].value));
|
||||
kt.push(getTypeOfValue(items[i][KEY]));
|
||||
vt.push(getTypeOfValue(items[i][VALUE]));
|
||||
}
|
||||
const t = makeMapType(makeUnionType(kt), makeUnionType(vt));
|
||||
return new MapLeafSequence(vr, t, items);
|
||||
|
||||
@@ -59,7 +59,7 @@ suite('Path', () => {
|
||||
});
|
||||
|
||||
test('map', async () => {
|
||||
const v = await newMap([1, 'foo', 'two', 'bar', false, 23, 2.3, 4.5]);
|
||||
const v = await newMap([[1, 'foo'], ['two', 'bar'], [false, 23], [2.3, 4.5]]);
|
||||
|
||||
await assertPathEqual('foo', v, new Path().addIndex(1));
|
||||
await assertPathEqual('bar', v, new Path().addIndex('two'));
|
||||
@@ -69,8 +69,8 @@ suite('Path', () => {
|
||||
});
|
||||
|
||||
test('struct.list.map', async () => {
|
||||
const m1 = await newMap(['a', 'foo', 'b','bar', 'c', 'car']);
|
||||
const m2 = await newMap(['d', 'dar', false, 'earth']);
|
||||
const m1 = await newMap([['a', 'foo'], ['b','bar'], ['c', 'car']]);
|
||||
const m2 = await newMap([['d', 'dar'], [false, 'earth']]);
|
||||
const l = await newList([m1, m2]);
|
||||
const s = newStruct('', {
|
||||
foo: l,
|
||||
|
||||
@@ -78,11 +78,13 @@ suite('walk', () => {
|
||||
|
||||
test('map', async () => {
|
||||
const expected = [];
|
||||
const entries = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
expected.push(i);
|
||||
expected.push(String('value' + i));
|
||||
expected.push('value' + i);
|
||||
entries.push([i, 'value' + i]);
|
||||
}
|
||||
const map = await newMap(Array.from(expected));
|
||||
const map = await newMap(entries);
|
||||
expected.push(map);
|
||||
|
||||
await callbackHappensOnce(map, ds);
|
||||
|
||||
Reference in New Issue
Block a user