Write type with value (#1406)

Write type for all values

Fixes #1308
This commit is contained in:
Erik Arvidsson
2016-05-03 16:52:22 -07:00
parent e69b163c6d
commit 963fbdaad6
28 changed files with 593 additions and 498 deletions
+2 -2
View File
@@ -23,9 +23,9 @@ type nomsShowTestSuite struct {
const (
res1 = "struct Commit {\n parents: Set<Ref<Parent<0>>>\n value: Value\n}({\n parents: {},\n value: sha1-7cecea5a8e3bcf30b35984eb7f592d98fa994a9a,\n})\n"
res2 = "\"test string\"\n"
res3 = "struct Commit {\n parents: Set<Ref<Parent<0>>>\n value: Value\n}({\n parents: {\n sha1-c247aef5a0626b12081d05cb9ce176eda1b7e65f,\n },\n value: sha1-b326291d2a568f39fa863ad63408711e676bc05b,\n})\n"
res3 = "struct Commit {\n parents: Set<Ref<Parent<0>>>\n value: Value\n}({\n parents: {\n sha1-4e7e3216cd7d2e7d5d7bc4fb3ede98ae6b2406c4,\n },\n value: sha1-b326291d2a568f39fa863ad63408711e676bc05b,\n})\n"
res4 = "List<Value>([\n \"elem1\",\n 2,\n \"elem3\",\n])\n"
res5 = "struct Commit {\n parents: Set<Ref<Parent<0>>>\n value: Value\n}({\n parents: {\n sha1-b2debb45e8edfefdce459470968eb7fea2fc2a04,\n },\n value: sha1-7cecea5a8e3bcf30b35984eb7f592d98fa994a9a,\n})\n"
res5 = "struct Commit {\n parents: Set<Ref<Parent<0>>>\n value: Value\n}({\n parents: {\n sha1-528e96673c69963f59df658a6e0ad3abe1561e75,\n },\n value: sha1-7cecea5a8e3bcf30b35984eb7f592d98fa994a9a,\n})\n"
)
func writeTestData(ds dataset.Dataset, value types.Value) types.Ref {
+1 -1
View File
@@ -30,7 +30,7 @@ func TestDatasetCommitTracker(t *testing.T) {
assert.False(ds2.Head().Get(datas.ValueField).Equals(ds1Commit))
assert.False(ds1.Head().Get(datas.ValueField).Equals(ds2Commit))
assert.Equal("sha1-73b50491e78c3098578941c44ee2f39b236d5eff", cs.Root().String())
assert.Equal("sha1-985b68f7727bc39e27badc3eca5d2178f44fb0a0", cs.Root().String())
}
func newDS(id string, cs *chunks.MemoryStore) Dataset {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@attic/noms",
"version": "21.1.0",
"version": "22.0.0",
"description": "Noms JS SDK",
"repository": "https://github.com/attic-labs/noms",
"main": "dist/commonjs/noms.js",
+2 -3
View File
@@ -5,7 +5,6 @@ import {assert} from 'chai';
import MemoryStore from './memory-store.js';
import BatchStore from './batch-store.js';
import {BatchStoreAdaptorDelegate} from './batch-store-adaptor.js';
import {stringType} from './type.js';
import {encodeNomsValue} from './encode.js';
suite('BatchStore', () => {
@@ -14,7 +13,7 @@ suite('BatchStore', () => {
const bs = new BatchStore(3, new BatchStoreAdaptorDelegate(ms));
const input = 'abc';
const c = encodeNomsValue(input, stringType);
const c = encodeNomsValue(input);
bs.schedulePut(c, new Set());
const chunk = await bs.get(c.ref);
@@ -26,7 +25,7 @@ suite('BatchStore', () => {
const bs = new BatchStore(3, new BatchStoreAdaptorDelegate(ms));
const input = 'abc';
const c = encodeNomsValue(input, stringType);
const c = encodeNomsValue(input);
bs.schedulePut(c, new Set());
let chunk = await bs.get(c.ref);
+5 -5
View File
@@ -117,23 +117,23 @@ suite('Blob', () => {
}
test('Blob 1K', async () => {
await blobTestSuite(10, 'sha1-cb21e6231cbcf57ff8a9e80c9cbc5b1e798bf9ea', 3, 2, 2);
await blobTestSuite(10, 'sha1-28e2f80d426cdb8bdbb347d00050b4d3fcb644a8', 3, 2, 2);
});
test('LONG: Blob 4K', async () => {
await blobTestSuite(12, 'sha1-53344f6e1d41ed9ce781e6cb3b999d3c5fc242a4', 9, 2, 2);
await blobTestSuite(12, 'sha1-5b2413e80d091f8b978ce927767e19e5655ac1a0', 9, 2, 2);
});
test('LONG: Blob 16K', async () => {
await blobTestSuite(14, 'sha1-50821a3ce89449bbc490194000c380e979e79132', 33, 2, 2);
await blobTestSuite(14, 'sha1-666ebeed9cbcbcb2da71c0bd578c7266a5abf9b2', 33, 2, 2);
});
test('LONG: Blob 64K', async () => {
await blobTestSuite(16, 'sha1-097098adc9ad9663c30ffcf69933b44165df1226', 4, 2, 2);
await blobTestSuite(16, 'sha1-a521ed352977cc544c2c98ac1a458f19fc551dce', 4, 2, 2);
});
test('LONG: Blob 256K', async () => {
await blobTestSuite(18, 'sha1-ff9c888571d2317bd201cfc2d31dbfd6a546c629', 13, 2, 2);
await blobTestSuite(18, 'sha1-4692cb536901b70e66109191b0091cfb2ed32eea', 2, 15, 2);
});
test('BlobWriter', async () => {
+4 -4
View File
@@ -42,8 +42,8 @@ suite('compare', () => {
const listC = await newList([4, 5, 6, 7], listOfNumberType);
assert.equal(compare(listA, listA), 0);
assert.equal(compare(listA, listB), 0);
assert.equal(compare(listA, listC), -1);
assert.equal(compare(listC, listA), 1);
assert.equal(compare(listA, listC), 1);
assert.equal(compare(listC, listA), -1);
});
});
@@ -73,8 +73,8 @@ suite('compare', () => {
const listC = await newList([4, 5, 6, 7], listOfNumberType);
assert.equal(compare(listA, listA), 0);
assert.equal(compare(listA, listB), 0);
assert.equal(compare(listA, listC), -1);
assert.equal(compare(listC, listA), 1);
assert.equal(compare(listA, listC), 1);
assert.equal(compare(listC, listA), -1);
});
});
+1 -2
View File
@@ -4,7 +4,6 @@ import type {Type} from './type.js';
import type {valueOrPrimitive} from './value.js';
import {Kind} from './noms-kind.js';
import {Value} from './value.js';
import {boolType} from './type.js';
import {getRef} from './get-ref.js';
import {invariant} from './assert.js';
@@ -66,7 +65,7 @@ function compareBools(v1: boolean, v2: boolean): number {
if (v1 === v2) {
return 0;
}
return getRef(v1, boolType).less(getRef(v2 ,boolType)) ? -1 : 1;
return getRef(v1).less(getRef(v2)) ? -1 : 1;
}
/**
+1 -2
View File
@@ -7,7 +7,6 @@ import {assert} from 'chai';
import {default as DataStore, getDatasTypes, newCommit} from './data-store.js';
import {invariant, notNull} from './assert.js';
import {newMap} from './map.js';
import {stringType} from './type.js';
import {encodeNomsValue} from './encode.js';
suite('DataStore', () => {
@@ -16,7 +15,7 @@ suite('DataStore', () => {
const ds = new DataStore(bs);
const input = 'abc';
const c = encodeNomsValue(input, stringType);
const c = encodeNomsValue(input);
const v1 = await ds.readValue(c.ref);
assert.equal(null, v1);
+196 -119
View File
@@ -3,8 +3,7 @@
import Chunk from './chunk.js';
import DataStore from './data-store.js';
import {makeTestingBatchStore} from './batch-store-adaptor.js';
import Ref from './ref.js';
import RefValue from './ref-value.js';
import type RefValue from './ref-value.js';
import {default as Struct, StructMirror} from './struct.js';
import type {TypeDesc} from './type.js';
import type {Value} from './value.js';
@@ -12,11 +11,11 @@ import {assert} from 'chai';
import {decodeNomsValue, JsonArrayReader} from './decode.js';
import {
boolType,
makeStructType,
makeListType,
makeMapType,
makeSetType,
makeRefType,
makeSetType,
makeStructType,
numberType,
stringType,
Type,
@@ -32,6 +31,7 @@ import {MapLeafSequence, NomsMap} from './map.js';
import {NomsBlob, newBlob} from './blob.js';
import {NomsSet, SetLeafSequence} from './set.js';
import {suite, test} from 'mocha';
import {equals} from './compare.js';
suite('Decode', () => {
function stringToUint8Array(s): Uint8Array {
@@ -42,7 +42,15 @@ suite('Decode', () => {
return bytes;
}
test('read', async () => {
function parseJson(s, ...replacements) {
s = s.replace(/\w+Kind/g, word => String(Kind[word.slice(0, -4)]));
let i = 0;
s = s.replace(/%s/g, () => String(replacements[i++]));
return JSON.parse(s);
}
test('read', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [1, 'hi', true];
const r = new JsonArrayReader(a, ds);
@@ -57,7 +65,7 @@ suite('Decode', () => {
assert.isTrue(r.atEnd());
});
test('read type as tag', async () => {
test('read type as tag', () => {
const ds = new DataStore(makeTestingBatchStore());
function doTest(expected: Type, a: Array<any>) {
const r = new JsonArrayReader(a, ds);
@@ -71,31 +79,32 @@ suite('Decode', () => {
doTest(makeStructType('S', {'x': boolType}), [Kind.Struct, 'S', ['x', Kind.Bool]]);
});
test('read primitives', async () => {
test('read primitives', () => {
const ds = new DataStore(makeTestingBatchStore());
async function doTest(expected: any, a: Array<any>): Promise<void> {
function doTest(expected: any, a: Array<any>): void {
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
assert.deepEqual(expected, v);
}
await doTest(true, [Kind.Bool, true]);
await doTest(false, [Kind.Bool, false]);
await doTest(0, [Kind.Number, '0']);
doTest(true, [Kind.Bool, true]);
doTest(false, [Kind.Bool, false]);
doTest(0, [Kind.Number, '0']);
await doTest(1e18, [Kind.Number, '1000000000000000000']);
await doTest(1e19, [Kind.Number, '10000000000000000000']);
await doTest(1e20, [Kind.Number, '1e+20']);
doTest(1e18, [Kind.Number, '1000000000000000000']);
doTest(1e19, [Kind.Number, '10000000000000000000']);
doTest(1e20, [Kind.Number, '1e+20']);
await doTest('hi', [Kind.String, 'hi']);
doTest('hi', [Kind.String, 'hi']);
});
test('read list of number', async () => {
test('read list of number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.List, Kind.Number, false, ['0', '1', '2', '3']];
const a = [Kind.List, Kind.Number, false,
[Kind.Number, '0', Kind.Number, '1', Kind.Number, '2', Kind.Number, '3']];
const r = new JsonArrayReader(a, ds);
const v: NomsList<number> = await r.readTopLevelValue();
const v: NomsList<number> = r.readValue();
invariant(v instanceof NomsList);
const tr = makeListType(numberType);
@@ -109,7 +118,7 @@ suite('Decode', () => {
const a = [Kind.List, Kind.Value, false,
[Kind.Number, '1', Kind.String, 'hi', Kind.Bool, true]];
const r = new JsonArrayReader(a, ds);
const v: NomsList<Value> = await r.readTopLevelValue();
const v: NomsList<Value> = r.readValue();
invariant(v instanceof NomsList);
const tr = makeListType(valueType);
@@ -119,11 +128,12 @@ suite('Decode', () => {
assert.strictEqual(true, await v.get(2));
});
test('read value list of number', async () => {
test('read value list of number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.Value, Kind.List, Kind.Number, false, ['0', '1', '2']];
const a = [Kind.Value, Kind.List, Kind.Number, false,
[Kind.Number, '0', Kind.Number, '1', Kind.Number, '2']];
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
invariant(v instanceof NomsList);
const tr = makeListType(numberType);
@@ -131,7 +141,7 @@ suite('Decode', () => {
assert.isTrue(l.equals(v));
});
test('read compound list', async () => {
test('read compound list', () => {
const ds = new DataStore(makeTestingBatchStore());
const ltr = makeListType(numberType);
const r1 = ds.writeValue(new NomsList(ltr, new ListLeafSequence(ds, ltr, [0])));
@@ -142,23 +152,25 @@ suite('Decode', () => {
new MetaTuple(r2, 2, 2),
new MetaTuple(r3, 3, 3),
];
const l:NomsList<number> = new NomsList(ltr, new IndexedMetaSequence(ds, ltr, tuples));
const l: NomsList<number> = new NomsList(ltr, new IndexedMetaSequence(ds, ltr, tuples));
const a = [Kind.List, Kind.Number, true,
[r1.targetRef.toString(), '1', '1',
r2.targetRef.toString(), '2', '2',
r3.targetRef.toString(), '3', '3']];
[r1.targetRef.toString(), Kind.Number, '1', '1',
r2.targetRef.toString(), Kind.Number, '2', '2',
r3.targetRef.toString(), Kind.Number, '3', '3']];
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
invariant(v instanceof NomsList);
assert.isTrue(v.ref.equals(l.ref));
});
test('read map of number to number', async () => {
test('read map of number to number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.Map, Kind.Number, Kind.Number, false, ['0', '1', '2', '3']];
const a = parseJson(`[MapKind, NumberKind, NumberKind, false,
[NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`);
const r = new JsonArrayReader(a, ds);
const v: NomsMap<number, number> = await r.readTopLevelValue();
const v: NomsMap<number, number> = r.readValue();
invariant(v instanceof NomsMap);
const t = makeMapType(numberType, numberType);
@@ -166,31 +178,34 @@ suite('Decode', () => {
assert.isTrue(v.equals(m));
});
test('read map of ref to number', async () => {
test('read map of ref to number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.Map, Kind.Ref, Kind.Value, Kind.Number, false,
['sha1-0000000000000000000000000000000000000001', '2',
'sha1-0000000000000000000000000000000000000002', '4']];
const rv1 = ds.writeValue(true);
const rv2 = ds.writeValue('hi');
const a = [
Kind.Map, Kind.Ref, Kind.Value, Kind.Number, false, [
Kind.Ref, Kind.Bool, rv1.targetRef.toString(), Kind.Number, '2',
Kind.Ref, Kind.String, rv2.targetRef.toString(), Kind.Number, '4',
],
];
const r = new JsonArrayReader(a, ds);
const v: NomsMap<RefValue<Value>, number> = await r.readTopLevelValue();
const v: NomsMap<RefValue<Value>, number> = r.readValue();
invariant(v instanceof NomsMap);
const refOfValueType = makeRefType(valueType);
const mapType = makeMapType(refOfValueType, numberType);
const rv1 = new RefValue(new Ref('sha1-0000000000000000000000000000000000000001'),
refOfValueType);
const rv2 = new RefValue(new Ref('sha1-0000000000000000000000000000000000000002'),
refOfValueType);
const m = new NomsMap(mapType, new MapLeafSequence(ds, mapType, [{key: rv1, value: 2},
{key: rv2, value: 4}]));
assert.isTrue(v.equals(m));
});
test('read value map of number to number', async () => {
test('read value map of number to number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.Value, Kind.Map, Kind.Number, Kind.Number, false, ['0', '1', '2', '3']];
const a = parseJson(`[ValueKind, MapKind, NumberKind, NumberKind, false,
[NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`);
const r = new JsonArrayReader(a, ds);
const v: NomsMap<number, number> = await r.readTopLevelValue();
const v: NomsMap<number, number> = r.readValue();
invariant(v instanceof NomsMap);
const t = makeMapType(numberType, numberType);
@@ -198,11 +213,12 @@ suite('Decode', () => {
assert.isTrue(v.equals(m));
});
test('read set of number', async () => {
test('read set of number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.Set, Kind.Number, false, ['0', '1', '2', '3']];
const a = parseJson(`[SetKind, NumberKind, false,
[NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`);
const r = new JsonArrayReader(a, ds);
const v: NomsSet<number> = await r.readTopLevelValue();
const v: NomsSet<number> = r.readValue();
invariant(v instanceof NomsSet);
const t = makeSetType(numberType);
@@ -210,34 +226,32 @@ suite('Decode', () => {
assert.isTrue(v.equals(s));
});
test('read compound set', async () => {
test('read compound set', () => {
const ds = new DataStore(makeTestingBatchStore());
const ltr = makeSetType(numberType);
const r1 = ds.writeValue(new NomsSet(ltr, new SetLeafSequence(ds, ltr, [0])));
const r2 = ds.writeValue(new NomsSet(ltr, new SetLeafSequence(ds, ltr, [1, 2])));
const r3 = ds.writeValue(new NomsSet(ltr, new SetLeafSequence(ds, ltr, [3, 4, 5])));
const r1 = ds.writeValue(new NomsSet(ltr, new SetLeafSequence(ds, ltr, [0, 1])));
const r2 = ds.writeValue(new NomsSet(ltr, new SetLeafSequence(ds, ltr, [2, 3, 4])));
const tuples = [
new MetaTuple(r1, 0, 1),
new MetaTuple(r2, 2, 2),
new MetaTuple(r3, 5, 3),
new MetaTuple(r1, 1, 2),
new MetaTuple(r2, 4, 3),
];
const l:NomsSet<number> = new NomsSet(ltr, new OrderedMetaSequence(ds, ltr, tuples));
const l: NomsSet<number> = new NomsSet(ltr, new OrderedMetaSequence(ds, ltr, tuples));
const a = [Kind.Set, Kind.Number, true,
[r1.targetRef.toString(), '0', '1',
r2.targetRef.toString(), '2', '2',
r3.targetRef.toString(), '5', '3']];
const a = parseJson(`[SetKind, NumberKind, true,
["%s", NumberKind, "1", "2", "%s", NumberKind, "4", "3"]]`,
r1.targetRef.toString(), r2.targetRef.toString());
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
invariant(v instanceof NomsSet);
assert.isTrue(v.ref.equals(l.ref));
});
test('read value set of number', async () => {
test('read value set of number', () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [Kind.Value, Kind.Set, Kind.Number, false, ['0', '1', '2', '3']];
const a = parseJson(`[ValueKind, SetKind, NumberKind, false,
[NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`);
const r = new JsonArrayReader(a, ds);
const v: NomsSet<number> = await r.readTopLevelValue();
const v: NomsSet<number> = r.readValue();
invariant(v instanceof NomsSet);
const t = makeSetType(numberType);
@@ -249,14 +263,14 @@ suite('Decode', () => {
notNull(s);
invariant(s instanceof Struct, 'expected instanceof struct');
const mirror = new StructMirror(s);
assert.deepEqual(desc, mirror.desc);
assert.isTrue(desc.equals(mirror.desc));
for (const key in data) {
assert.deepEqual(data[key], mirror.get(key));
assert.isTrue(equals(data[key], notNull(mirror.get(key))));
}
}
test('test read struct', async () => {
test('test read struct', () => {
const ds = new DataStore(makeTestingBatchStore());
const tr = makeStructType('A1', {
'x': numberType,
@@ -264,13 +278,10 @@ suite('Decode', () => {
'b': boolType,
});
const a = [Kind.Struct, 'A1', [
'b', Kind.Bool,
's', Kind.String,
'x', Kind.Number,
], true, 'hi', '42'];
const a = parseJson(`[StructKind, "A1", ["b", BoolKind, "s", StringKind, "x", NumberKind],
BoolKind, true, StringKind, "hi", NumberKind, "42"]`);
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
assertStruct(v, tr.desc, {
x: 42,
@@ -279,7 +290,7 @@ suite('Decode', () => {
});
});
test('test read struct with list', async () => {
test('test read struct with list', () => {
const ds = new DataStore(makeTestingBatchStore());
const ltr = makeListType(numberType);
const tr = makeStructType('A4', {
@@ -288,13 +299,21 @@ suite('Decode', () => {
's': stringType,
});
const a = [Kind.Struct, 'A4', [
'b', Kind.Bool,
'l', Kind.List, Kind.Number,
's', Kind.String,
], true, false, ['0', '1', '2'], 'hi'];
const a = parseJson(`[
StructKind, "A4", [
"b", BoolKind,
"l", ListKind, NumberKind,
"s", StringKind
],
BoolKind, true,
ListKind, NumberKind, false, [
NumberKind, "0",
NumberKind, "1",
NumberKind, "2"
],
StringKind, "hi"]`);
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
assertStruct(v, tr.desc, {
b: true,
@@ -303,7 +322,7 @@ suite('Decode', () => {
});
});
test('test read struct with value', async () => {
test('test read struct with value', () => {
const ds = new DataStore(makeTestingBatchStore());
const tr = makeStructType('A5', {
'b': boolType,
@@ -311,10 +330,19 @@ suite('Decode', () => {
's': stringType,
});
const a = [Kind.Struct, 'A5', ['b', Kind.Bool, 's', Kind.String, 'v', Kind.Value],
true, 'hi', Kind.Number, '42'];
const a = parseJson(`[
StructKind, "A5", [
"b", BoolKind,
"s", StringKind,
"v", ValueKind
],
BoolKind, true,
StringKind, "hi",
NumberKind, "42"
]`);
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
assertStruct(v, tr.desc, {
b: true,
@@ -323,7 +351,7 @@ suite('Decode', () => {
});
});
test('test read value struct', async () => {
test('test read value struct', () => {
const ds = new DataStore(makeTestingBatchStore());
const tr = makeStructType('A1', {
'x': numberType,
@@ -331,14 +359,19 @@ suite('Decode', () => {
'b': boolType,
});
const a = [Kind.Value, Kind.Struct, 'A1', [
'b', Kind.Bool,
's', Kind.String,
'x', Kind.Number,
],
true, 'hi', '42'];
const a = parseJson(`[
ValueKind, StructKind, "A1", [
"b", BoolKind,
"s", StringKind,
"x", NumberKind
],
BoolKind, true,
StringKind, "hi",
NumberKind, "42"
]`);
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
assertStruct(v, tr.desc, {
x: 42,
@@ -354,12 +387,19 @@ suite('Decode', () => {
'i': numberType,
});
const a = [Kind.Value, Kind.Map, Kind.String,
Kind.Struct, 's', ['b', Kind.Bool, 'i', Kind.Number],
false, ['bar', false, '2', 'baz', false, '1', 'foo', true, '3']];
const a = parseJson(`[
MapKind, StringKind, StructKind, "s", ["b", BoolKind, "i", NumberKind], false, [
StringKind, "bar", StructKind, "s", ["b", BoolKind, "i", NumberKind],
BoolKind, false, NumberKind, "2",
StringKind, "baz", StructKind, "s", ["b", BoolKind, "i", NumberKind],
BoolKind, false, NumberKind, "1",
StringKind, "foo", StructKind, "s", ["b", BoolKind, "i", NumberKind],
BoolKind, true, NumberKind, "3"
]
]`);
const r = new JsonArrayReader(a, ds);
const v: NomsMap<string, Struct> = await r.readTopLevelValue();
const v: NomsMap<string, Struct> = r.readValue();
invariant(v instanceof NomsMap);
assert.strictEqual(3, v.size);
@@ -371,12 +411,14 @@ suite('Decode', () => {
test('decodeNomsValue', () => {
const ds = new DataStore(makeTestingBatchStore());
const chunk = Chunk.fromString(
`t [${Kind.Value}, ${Kind.Set}, ${Kind.Number}, false, ["0", "1", "2", "3"]]`);
`t [${Kind.Value},${Kind.Set},${Kind.Number},false,[${Kind.Number},"0",${
Kind.Number},"1",${Kind.Number},"2",${Kind.Number},"3"]]`);
const v = decodeNomsValue(chunk, new DataStore(makeTestingBatchStore()));
invariant(v instanceof NomsSet);
const t = makeSetType(numberType);
const s: NomsSet<number> = new NomsSet(t, new SetLeafSequence(ds, t, [0, 1, 2, 3]));
assert.isTrue(v.equals(s));
});
@@ -392,17 +434,33 @@ suite('Decode', () => {
// }
// Commit value
const commitChunk = makeChunk(
[Kind.Struct, 'Commit',
['value', Kind.Value, 'parents', Kind.Set, Kind.Ref, Kind.Parent, 0],
false, [], Kind.Number, '1']);
const commitChunk = makeChunk([
Kind.Struct, 'Commit', [
'value', Kind.Value,
'parents', Kind.Set, Kind.Ref, Kind.Parent, 0,
],
Kind.Set, Kind.Ref, Kind.Struct, 'Commit', [
'value', Kind.Value,
'parents', Kind.Set, Kind.Ref, Kind.Parent, 0,
], false, [],
Kind.Number, '1']);
const commitRef = commitChunk.ref;
bs.schedulePut(commitChunk, new Set());
// Root
const rootChunk = makeChunk([Kind.Map, Kind.String, Kind.Ref, Kind.Struct, 'Commit',
['parents', Kind.Set, Kind.Ref, Kind.Parent, 0, 'value', Kind.Value],
false, ['counter', commitRef.toString()]]);
const rootChunk = makeChunk([
Kind.Map, Kind.String, Kind.Ref, Kind.Struct, 'Commit', [
'parents', Kind.Set, Kind.Ref, Kind.Parent, 0,
'value', Kind.Value,
],
false, [
Kind.String, 'counter',
Kind.Ref, Kind.Struct, 'Commit', [
'parents', Kind.Set, Kind.Ref, Kind.Parent, 0,
'value', Kind.Value,
], commitRef.toString(),
],
]);
const rootRef = rootChunk.ref;
bs.schedulePut(rootChunk, new Set());
@@ -444,13 +502,11 @@ suite('Decode', () => {
test('inline blob', async () => {
const ds = new DataStore(makeTestingBatchStore());
const a = [
Kind.List, Kind.Blob, false,
[false, encodeBase64(stringToUint8Array('hello')),
false, encodeBase64(stringToUint8Array('world'))],
];
const a = parseJson(`[
ListKind, BlobKind, false, [BlobKind, false, "%s", BlobKind, false, "%s"]
]`, encodeBase64(stringToUint8Array('hello')), encodeBase64(stringToUint8Array('world')));
const r = new JsonArrayReader(a, ds);
const v: NomsList<NomsBlob> = await r.readTopLevelValue();
const v: NomsList<NomsBlob> = r.readValue();
invariant(v instanceof NomsList);
assert.strictEqual(2, v.length);
@@ -467,10 +523,11 @@ suite('Decode', () => {
const r1 = ds.writeValue(await newBlob(stringToUint8Array('hi')));
const r2 = ds.writeValue(await newBlob(stringToUint8Array('world')));
const a = [Kind.Blob, true,
[r1.targetRef.toString(), '2', '2', r2.targetRef.toString(), '5', '5']];
const a = parseJson(`[BlobKind, true, [
"%s", NumberKind, "2", "2",
"%s", NumberKind, "5", "5"]]`, r1.targetRef, r2.targetRef);
const r = new JsonArrayReader(a, ds);
const v: NomsBlob = await r.readTopLevelValue();
const v: NomsBlob = r.readValue();
invariant(v instanceof NomsBlob);
const reader = v.getReader();
@@ -480,7 +537,7 @@ suite('Decode', () => {
assert.deepEqual(await reader.read(), {done: true});
});
test('recursive struct', async () => {
test('recursive struct', () => {
const ds = new DataStore(makeTestingBatchStore());
// struct A {
@@ -501,13 +558,33 @@ suite('Decode', () => {
tb.desc.fields['a'] = makeListType(ta);
tb.desc.fields['b'] = makeListType(tb);
const a = [Kind.Struct, 'A',
['b', Kind.Struct, 'B', [
'a', Kind.List, Kind.Parent, 1,
'b', Kind.List, Kind.Parent, 0,
]], false, [], false, []];
const a = parseJson(`[
StructKind, "A", [
"b", StructKind, "B", [
"a", ListKind, ParentKind, 1,
"b", ListKind, ParentKind, 0
]
],
StructKind, "B", [
"a", ListKind, StructKind, "A", [
"b", ParentKind, 1
],
"b", ListKind, ParentKind, 0
],
ListKind, StructKind, "A", [
"b", StructKind, "B", [
"a", ListKind, ParentKind, 1,
"b", ListKind, ParentKind, 0
]
], false, [],
ListKind, StructKind, "B", [
"a", ListKind, StructKind, "A", [
"b", ParentKind, 1
],
"b", ListKind, ParentKind, 0
], false, []]`);
const r = new JsonArrayReader(a, ds);
const v = await r.readTopLevelValue();
const v = r.readValue();
assert.isTrue(v.type.equals(ta));
assert.isTrue(v.b.type.equals(tb));
+13 -24
View File
@@ -17,7 +17,7 @@ import {
Type,
typeType,
} from './type.js';
import {indexTypeForMetaSequence, MetaTuple, newMetaSequenceFromData} from './meta-sequence.js';
import {MetaTuple, newMetaSequenceFromData} from './meta-sequence.js';
import {invariant} from './assert.js';
import {isPrimitiveKind, Kind} from './noms-kind.js';
import {ListLeafSequence, NomsList} from './list.js';
@@ -137,17 +137,15 @@ export class JsonArrayReader {
throw new Error('Unreachable');
}
readBlobLeafSequence(): BlobLeafSequence {
const bytes = decodeBase64(this.readString());
return new BlobLeafSequence(this._ds, bytes);
}
readSequence(t: Type): Array<any> {
const elemType = t.elemTypes[0];
readSequence(): Array<any> {
const list = [];
while (!this.atEnd()) {
const v = this.readValueWithoutTag(elemType);
const v = this.readValue();
list.push(v);
}
@@ -155,22 +153,20 @@ export class JsonArrayReader {
}
readListLeafSequence(t: Type): ListLeafSequence {
const seq = this.readSequence(t);
const seq = this.readSequence();
return new ListLeafSequence(this._ds, t, seq);
}
readSetLeafSequence(t: Type): SetLeafSequence {
const seq = this.readSequence(t);
const seq = this.readSequence();
return new SetLeafSequence(this._ds, t, seq);
}
readMapLeafSequence(t: Type): MapLeafSequence {
const keyType = t.elemTypes[0];
const valueType = t.elemTypes[1];
const entries = [];
while (!this.atEnd()) {
const k = this.readValueWithoutTag(keyType);
const v = this.readValueWithoutTag(valueType);
const k = this.readValue();
const v = this.readValue();
entries.push({key: k, value: v});
}
@@ -179,10 +175,9 @@ export class JsonArrayReader {
readMetaSequence(t: Type): any {
const data: Array<MetaTuple> = [];
const indexType = indexTypeForMetaSequence(t);
while (!this.atEnd()) {
const ref = this.readRefValue(makeRefType(t));
const v = this.readValueWithoutTag(indexType);
const v = this.readValue();
const numLeaves = this.readInt();
data.push(new MetaTuple(ref, v, numLeaves));
}
@@ -195,13 +190,8 @@ export class JsonArrayReader {
return new RefValue(ref, t);
}
readTopLevelValue(): any {
readValue(): any {
const t = this.readTypeAsTag([]);
return this.readValueWithoutTag(t);
}
readValueWithoutTag(t: Type): any {
// TODO: Verify read values match tagged kinds.
switch (t.kind) {
case Kind.Blob: {
const isMeta = this.readBool();
@@ -222,8 +212,7 @@ export class JsonArrayReader {
case Kind.String:
return this.readString();
case Kind.Value: {
const t2 = this.readTypeAsTag([]);
return this.readValueWithoutTag(t2);
return this.readValue();
}
case Kind.List: {
const isMeta = this.readBool();
@@ -293,8 +282,8 @@ export class JsonArrayReader {
const data: {[key: string]: any} = Object.create(null);
desc.forEachField((name: string, type: Type) => {
const v = this.readValueWithoutTag(type);
desc.forEachField((name: string) => {
const v = this.readValue();
data[name] = v;
});
@@ -330,7 +319,7 @@ export function decodeNomsValue(chunk: Chunk, vr: ValueReader): valueOrPrimitive
case typedTag: {
const payload = JSON.parse(new Chunk(new Uint8Array(chunk.data.buffer, 2)).toString());
const reader = new JsonArrayReader(payload, vr);
return reader.readTopLevelValue();
return reader.readValue();
}
case blobTag:
return new NomsBlob(new BlobLeafSequence(vr, new Uint8Array(chunk.data.buffer, 2)));
+99 -116
View File
@@ -24,39 +24,39 @@ import {
} from './type.js';
import {IndexedMetaSequence, MetaTuple, OrderedMetaSequence} from './meta-sequence.js';
import {Kind} from './noms-kind.js';
import {newList, ListLeafSequence, NomsList} from './list.js';
import {newMap, MapLeafSequence, NomsMap} from './map.js';
import {newSet, NomsSet, SetLeafSequence} from './set.js';
import {ListLeafSequence, NomsList} from './list.js';
import {MapLeafSequence, NomsMap} from './map.js';
import {NomsSet, SetLeafSequence} from './set.js';
import {newBlob} from './blob.js';
import DataStore from './data-store.js';
import type {valueOrPrimitive} from './value.js';
suite('Encode', () => {
test('write primitives', () => {
function f(k: NomsKind, t:Type, v: valueOrPrimitive, ex: valueOrPrimitive) {
function f(k: NomsKind, v: valueOrPrimitive, ex: valueOrPrimitive) {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
w.writeTopLevel(t, v);
w.writeValue(v);
assert.deepEqual([k, ex], w.array);
}
f(Kind.Bool, boolType, true, true);
f(Kind.Bool, boolType, false, false);
f(Kind.Bool, true, true);
f(Kind.Bool, false, false);
f(Kind.Number, numberType, 0, '0');
f(Kind.Number, 0, '0');
f(Kind.Number, numberType, 1e18, '1000000000000000000');
f(Kind.Number, numberType, 1e19, '10000000000000000000');
f(Kind.Number, numberType, 1e20, '1e+20');
f(Kind.Number, 1e18, '1000000000000000000');
f(Kind.Number, 1e19, '10000000000000000000');
f(Kind.Number, 1e20, '1e+20');
f(Kind.String, stringType, 'hi', 'hi');
f(Kind.String, 'hi', 'hi');
});
test('write simple blob', async () => {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
const blob = await newBlob(new Uint8Array([0x00, 0x01]));
w.writeTopLevel(blobType, blob);
w.writeValue(blob);
assert.deepEqual([Kind.Blob, false, 'AAE='], w.array);
});
@@ -66,8 +66,9 @@ suite('Encode', () => {
const tr = makeCompoundType(Kind.List, numberType);
const l = new NomsList(tr, new ListLeafSequence(ds, tr, [0, 1, 2, 3]));
w.writeTopLevel(tr, l);
assert.deepEqual([Kind.List, Kind.Number, false, ['0', '1', '2', '3']], w.array);
w.writeValue(l);
assert.deepEqual([Kind.List, Kind.Number, false,
[Kind.Number, '0', Kind.Number, '1', Kind.Number, '2', Kind.Number, '3']], w.array);
});
test('write list of value', async () => {
@@ -75,13 +76,13 @@ suite('Encode', () => {
const w = new JsonArrayWriter(ds);
const tr = makeCompoundType(Kind.List, valueType);
const l = new NomsList(tr, new ListLeafSequence(ds, tr, ['0', '1', '2', '3']));
w.writeTopLevel(tr, l);
const l = new NomsList(tr, new ListLeafSequence(ds, tr, ['0', 1, '2', true]));
w.writeValue(l);
assert.deepEqual([Kind.List, Kind.Value, false, [
Kind.String, '0',
Kind.String, '1',
Kind.Number, '1',
Kind.String, '2',
Kind.String, '3',
Kind.Bool, true,
]], w.array);
});
@@ -89,15 +90,17 @@ suite('Encode', () => {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
const it = makeCompoundType(Kind.List, numberType);
const tr = makeCompoundType(Kind.List, it);
const it = makeListType(numberType);
const tr = makeListType(it);
const v = new NomsList(tr, new ListLeafSequence(ds, tr, [
new NomsList(tr, new ListLeafSequence(ds, it, [0])),
new NomsList(tr, new ListLeafSequence(ds, it, [1, 2, 3])),
new NomsList(it, new ListLeafSequence(ds, it, [0])),
new NomsList(it, new ListLeafSequence(ds, it, [1, 2, 3])),
]));
w.writeTopLevel(tr, v);
assert.deepEqual([Kind.List, Kind.List, Kind.Number, false, [false, ['0'], false,
['1', '2', '3']]], w.array);
w.writeValue(v);
assert.deepEqual([Kind.List, Kind.List, Kind.Number, false, [
Kind.List, Kind.Number, false, [Kind.Number, '0'],
Kind.List, Kind.Number, false, [Kind.Number, '1', Kind.Number, '2', Kind.Number, '3']]],
w.array);
});
test('write leaf set', async () => {
@@ -106,8 +109,9 @@ suite('Encode', () => {
const tr = makeCompoundType(Kind.Set, numberType);
const v = new NomsSet(tr, new SetLeafSequence(ds, tr, [0, 1, 2, 3]));
w.writeTopLevel(tr, v);
assert.deepEqual([Kind.Set, Kind.Number, false, ['0', '1', '2', '3']], w.array);
w.writeValue(v);
assert.deepEqual([Kind.Set, Kind.Number, false,
[Kind.Number, '0', Kind.Number, '1', Kind.Number, '2', Kind.Number, '3']], w.array);
});
test('write compound set', async () => {
@@ -124,27 +128,29 @@ suite('Encode', () => {
];
const l = new NomsSet(ltr, new OrderedMetaSequence(ds, ltr, tuples));
w.writeTopLevel(ltr, l);
w.writeValue(l);
assert.deepEqual([Kind.Set, Kind.Number, true,
[r1.targetRef.toString(), '0', '1',
r2.targetRef.toString(), '2', '2',
r3.targetRef.toString(), '5', '3']], w.array);
[r1.targetRef.toString(), Kind.Number, '0', '1',
r2.targetRef.toString(), Kind.Number, '2', '2',
r3.targetRef.toString(), Kind.Number, '5', '3']], w.array);
});
test('write set of set', async () => {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
const st = makeCompoundType(Kind.Set, numberType);
const tr = makeCompoundType(Kind.Set, st);
const st = makeSetType(numberType);
const tr = makeSetType(st);
const v = new NomsSet(tr, new SetLeafSequence(ds, tr, [
new NomsSet(tr, new SetLeafSequence(ds, st, [0])),
new NomsSet(tr, new SetLeafSequence(ds, st, [1, 2, 3])),
new NomsSet(st, new SetLeafSequence(ds, st, [0])),
new NomsSet(st, new SetLeafSequence(ds, st, [1, 2, 3])),
]));
w.writeTopLevel(tr, v);
assert.deepEqual([Kind.Set, Kind.Set, Kind.Number, false, [false, ['0'], false,
['1', '2', '3']]], w.array);
w.writeValue(v);
assert.deepEqual([Kind.Set, Kind.Set, Kind.Number, false, [
Kind.Set, Kind.Number, false, [Kind.Number, '0'],
Kind.Set, Kind.Number, false, [Kind.Number, '1', Kind.Number, '2', Kind.Number, '3']]],
w.array);
});
test('write map', async() => {
@@ -154,24 +160,29 @@ suite('Encode', () => {
const tr = makeCompoundType(Kind.Map, stringType, boolType);
const v = new NomsMap(tr, new MapLeafSequence(ds, tr, [{key: 'a', value: false},
{key:'b', value:true}]));
w.writeTopLevel(tr, v);
assert.deepEqual([Kind.Map, Kind.String, Kind.Bool, false, ['a', false, 'b', true]], w.array);
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);
});
test('write map of map', async() => {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
const kt = makeCompoundType(Kind.Map, stringType, numberType);
const vt = makeCompoundType(Kind.Set, boolType);
const tr = makeCompoundType(Kind.Map, kt, vt);
const kt = makeMapType(stringType, numberType);
const vt = makeSetType(boolType);
const tr = makeMapType(kt, vt);
// Map<Map<String, Number>, Set<Bool>>({{'a': 0}: {true}})
const s = new NomsSet(vt, new SetLeafSequence(ds, vt, [true]));
const m1 = new NomsMap(kt, new MapLeafSequence(ds, kt, [{key: 'a', value: 0}]));
const v = new NomsMap(kt, new MapLeafSequence(ds, tr, [{key: m1, value: s}]));
w.writeTopLevel(tr, v);
assert.deepEqual([Kind.Map, Kind.Map, Kind.String, Kind.Number, Kind.Set, Kind.Bool, false,
[false, ['a', '0'], false, [true]]], w.array);
const v = new NomsMap(tr, new MapLeafSequence(ds, tr, [{key: m1, value: s}]));
w.writeValue(v);
assert.deepEqual([Kind.Map,
Kind.Map, Kind.String, Kind.Number,
Kind.Set, Kind.Bool, false, [
Kind.Map, Kind.String, Kind.Number, false, [Kind.String, 'a', Kind.Number, '0'],
Kind.Set, Kind.Bool, false, [Kind.Bool, true]]], w.array);
});
test('write empty struct', async() => {
@@ -181,7 +192,7 @@ suite('Encode', () => {
const type = makeStructType('S', {});
const v = newStruct(type, {});
w.writeTopLevel(type, v);
w.writeValue(v);
assert.deepEqual([Kind.Struct, 'S', []], w.array);
});
@@ -196,27 +207,30 @@ suite('Encode', () => {
const v = newStruct(type, {x: 42, b: true});
w.writeTopLevel(type, v);
assert.deepEqual([Kind.Struct, 'S', ['b', Kind.Bool, 'x', Kind.Number], true, '42'], w.array);
w.writeValue(v);
assert.deepEqual([Kind.Struct, 'S', ['b', Kind.Bool, 'x', Kind.Number],
Kind.Bool, true, Kind.Number, '42'], w.array);
});
test('write struct with list', async() => {
const ds = new DataStore(makeTestingBatchStore());
let w = new JsonArrayWriter(ds);
const ltr = makeCompoundType(Kind.List, stringType);
const ltr = makeListType(stringType);
const type = makeStructType('S', {
'l': ltr,
});
let v = newStruct(type, {l: new NomsList(ltr, new ListLeafSequence(ds, ltr, ['a', 'b']))});
w.writeTopLevel(type, v);
assert.deepEqual([Kind.Struct, 'S', ['l', Kind.List, Kind.String], false, ['a', 'b']], w.array);
w.writeValue(v);
assert.deepEqual([Kind.Struct, 'S', ['l', Kind.List, Kind.String],
Kind.List, Kind.String, false, [Kind.String, 'a', Kind.String, 'b']], w.array);
v = newStruct(type, {l: new NomsList(ltr, new ListLeafSequence(ds, ltr, []))});
w = new JsonArrayWriter(ds);
w.writeTopLevel(type, v);
assert.deepEqual([Kind.Struct, 'S', ['l', Kind.List, Kind.String], false, []], w.array);
w.writeValue(v);
assert.deepEqual([Kind.Struct, 'S', ['l', Kind.List, Kind.String],
Kind.List, Kind.String, false, []], w.array);
});
test('write struct with struct', async () => {
@@ -231,9 +245,10 @@ suite('Encode', () => {
});
const v = newStruct(sType, {s: newStruct(s2Type, {x: 42})});
w.writeTopLevel(sType, v);
w.writeValue(v);
assert.deepEqual([Kind.Struct, 'S',
['s', Kind.Struct, 'S2', ['x', Kind.Number]], '42'], w.array);
['s', Kind.Struct, 'S2', ['x', Kind.Number]],
Kind.Struct, 'S2', ['x', Kind.Number], Kind.Number, '42'], w.array);
});
test('write compound list', async () => {
@@ -250,11 +265,29 @@ suite('Encode', () => {
];
const l = new NomsList(ltr, new IndexedMetaSequence(ds, ltr, tuples));
w.writeTopLevel(ltr, l);
w.writeValue(l);
assert.deepEqual([Kind.List, Kind.Number, true,
[r1.targetRef.toString(), '1', '1',
r2.targetRef.toString(), '2', '2',
r3.targetRef.toString(), '3', '3']], w.array);
[r1.targetRef.toString(), Kind.Number, '1', '1',
r2.targetRef.toString(), Kind.Number, '2', '2',
r3.targetRef.toString(), Kind.Number, '3', '3']], w.array);
});
test('write compound set with bool', async () => {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
const str = makeSetType(boolType);
const r1 = ds.writeValue(new NomsSet(str, new SetLeafSequence(ds, str, [true])));
const r2 = ds.writeValue(new NomsSet(str, new SetLeafSequence(ds, str, [false])));
const tuples = [
new MetaTuple(r1, true, 1),
new MetaTuple(r2, false, 1),
];
const l = new NomsSet(str, new OrderedMetaSequence(ds, str, tuples));
w.writeValue(l);
assert.deepEqual([Kind.Set, Kind.Bool, true,
[r1.targetRef.toString(), Kind.Bool, true, '1',
r2.targetRef.toString(), Kind.Bool, false, '1']], w.array);
});
test('write type value', async () => {
@@ -262,7 +295,7 @@ suite('Encode', () => {
const test = (expected: Array<any>, v: Type) => {
const w = new JsonArrayWriter(ds);
w.writeTopLevel(v.type, v);
w.writeValue(v);
assert.deepEqual(w.array, expected);
};
@@ -304,7 +337,7 @@ suite('Encode', () => {
const ds = new DataStore(makeTestingBatchStore());
const blob = await newBlob(stringToUint8Array('hi'));
const chunk = encodeNomsValue(blob, blobType, ds);
const chunk = encodeNomsValue(blob, ds);
assert.equal(4, chunk.data.length);
assert.deepEqual(stringToUint8Array('b hi'), chunk.data);
@@ -318,7 +351,7 @@ suite('Encode', () => {
view.setUint8(2 + i, i);
}
const blob2 = await newBlob(bytes);
const chunk2 = encodeNomsValue(blob2, blobType, ds);
const chunk2 = encodeNomsValue(blob2, ds);
assert.equal(buffer2.byteLength, chunk2.data.buffer.byteLength);
assert.deepEqual(buffer2, chunk2.data.buffer);
});
@@ -329,58 +362,8 @@ suite('Encode', () => {
const ref = Ref.parse('sha1-0123456789abcdef0123456789abcdef01234567');
const t = makeCompoundType(Kind.Ref, blobType);
const v = new RefValue(ref, t);
w.writeTopLevel(t, v);
w.writeValue(v);
assert.deepEqual([Kind.Ref, Kind.Blob, ref.toString()], w.array);
});
test('type errors', async () => {
const ds = new DataStore(makeTestingBatchStore());
const w = new JsonArrayWriter(ds);
const test = (et, at, t, v) => {
try {
w.writeTopLevel(t, v);
} catch (ex) {
assert.equal(ex.message, `Failed to write ${et}. Invalid type: ${at}`);
return;
}
assert.ok(false, `Expected error, 'Failed to write ${et}. Invalid type: ${at}' but Got none`);
};
test('Number', 'String', numberType, 'hi');
test('Bool', 'String', boolType, 'hi');
test('Blob', 'String', blobType, 'hi');
test('String', 'Number', stringType, 42);
test('Bool', 'Number', boolType, 42);
test('Blob', 'Number', blobType, 42);
test('Number', 'Bool', numberType, true);
test('String', 'Bool', stringType, true);
test('Blob', 'Bool', blobType, true);
const blob = await newBlob(new Uint8Array([0, 1]));
test('Number', 'Blob', numberType, blob);
test('String', 'Blob', stringType, blob);
test('Bool', 'Blob', boolType, blob);
const list = await newList([0, 1], makeListType(numberType));
test('Number', 'List<Number>', numberType, list);
test('String', 'List<Number>', stringType, list);
test('Bool', 'List<Number>', boolType, list);
test('Blob', 'List<Number>', blobType, list);
const map = await newMap(['zero', 1], makeMapType(stringType, numberType));
test('Number', 'Map<String, Number>', numberType, map);
test('String', 'Map<String, Number>', stringType, map);
test('Bool', 'Map<String, Number>', boolType, map);
test('Blob', 'Map<String, Number>', blobType, map);
const set = await newSet([0, 1], makeSetType(numberType));
test('Number', 'Set<Number>', numberType, set);
test('String', 'Set<Number>', stringType, set);
test('Bool', 'Set<Number>', boolType, set);
test('Blob', 'Set<Number>', blobType, set);
});
});
+21 -32
View File
@@ -6,7 +6,7 @@ import {default as Struct, StructMirror} from './struct.js';
import type {NomsKind} from './noms-kind.js';
import {encode as encodeBase64} from './base64.js';
import {StructDesc, Type, getTypeOfValue} from './type.js';
import {indexTypeForMetaSequence, MetaTuple} from './meta-sequence.js';
import {MetaTuple} from './meta-sequence.js';
import {invariant} from './assert.js';
import {isPrimitiveKind, Kind} from './noms-kind.js';
import {ListLeafSequence, NomsList} from './list.js';
@@ -84,12 +84,7 @@ export class JsonArrayWriter {
}
}
writeTopLevel(t: Type, v: valueOrPrimitive) {
this.writeTypeAsTag(t, []);
this.writeValue(v, t);
}
maybeWriteMetaSequence(v: Sequence, t: Type): boolean {
maybeWriteMetaSequence(v: Sequence): boolean {
if (!v.isMeta) {
this.write(false);
return false;
@@ -97,7 +92,6 @@ export class JsonArrayWriter {
this.write(true);
const w2 = new JsonArrayWriter(this._vw);
const indexType = indexTypeForMetaSequence(t);
for (let i = 0; i < v.items.length; i++) {
const tuple = v.items[i];
invariant(tuple instanceof MetaTuple);
@@ -106,21 +100,23 @@ export class JsonArrayWriter {
this._vw.writeValue(child);
}
w2.writeRefValue(tuple.ref);
w2.writeValue(tuple.value, indexType);
w2.writeValue(tuple.value);
w2.writeInt(tuple.numLeaves);
}
this.write(w2.array);
return true;
}
writeValue(v: valueOrPrimitive, t: Type) {
writeValue(v: valueOrPrimitive) {
const t = getTypeOfValue(v);
this.writeTypeAsTag(t, []);
switch (t.kind) {
case Kind.Blob: {
invariant(v instanceof NomsBlob || v instanceof Sequence,
() => `Failed to write Blob. Invalid type: ${describeTypeOfValue(v)}`);
const sequence: Sequence = v instanceof NomsBlob ? v.sequence : v;
if (this.maybeWriteMetaSequence(sequence, t)) {
if (this.maybeWriteMetaSequence(sequence)) {
break;
}
@@ -148,14 +144,13 @@ export class JsonArrayWriter {
() => `Failed to write List. Invalid type: ${describeTypeOfValue(v)}`);
const sequence: Sequence = v instanceof NomsList ? v.sequence : v;
if (this.maybeWriteMetaSequence(sequence, t)) {
if (this.maybeWriteMetaSequence(sequence)) {
break;
}
invariant(sequence instanceof ListLeafSequence);
const w2 = new JsonArrayWriter(this._vw);
const elemType = t.elemTypes[0];
sequence.items.forEach(sv => w2.writeValue(sv, elemType));
sequence.items.forEach(sv => w2.writeValue(sv));
this.write(w2.array);
break;
}
@@ -164,17 +159,15 @@ export class JsonArrayWriter {
() => `Failed to write Map. Invalid type: ${describeTypeOfValue(v)}`);
const sequence: Sequence = v instanceof NomsMap ? v.sequence : v;
if (this.maybeWriteMetaSequence(sequence, t)) {
if (this.maybeWriteMetaSequence(sequence)) {
break;
}
invariant(sequence instanceof MapLeafSequence);
const w2 = new JsonArrayWriter(this._vw);
const keyType = t.elemTypes[0];
const valueType = t.elemTypes[1];
sequence.items.forEach(entry => {
w2.writeValue(entry.key, keyType);
w2.writeValue(entry.value, valueType);
w2.writeValue(entry.key);
w2.writeValue(entry.value);
});
this.write(w2.array);
break;
@@ -190,18 +183,15 @@ export class JsonArrayWriter {
() => `Failed to write Set. Invalid type: ${describeTypeOfValue(v)}`);
const sequence: Sequence = v instanceof NomsSet ? v.sequence : v;
if (this.maybeWriteMetaSequence(sequence, t)) {
if (this.maybeWriteMetaSequence(sequence)) {
break;
}
invariant(sequence instanceof SetLeafSequence);
const w2 = new JsonArrayWriter(this._vw);
const elemType = t.elemTypes[0];
const elems = [];
sequence.items.forEach(v => {
elems.push(v);
w2.writeValue(v);
});
elems.forEach(elem => w2.writeValue(elem, elemType));
this.write(w2.array);
break;
}
@@ -212,9 +202,7 @@ export class JsonArrayWriter {
break;
}
case Kind.Value: {
const valueType = getTypeOfValue(v);
this.writeTypeAsTag(valueType, []);
this.writeValue(v, valueType);
this.writeValue(v);
break;
}
case Kind.Struct:
@@ -284,14 +272,14 @@ export class JsonArrayWriter {
writeStruct(s: Struct) {
const mirror = new StructMirror(s);
mirror.forEachField(field => {
this.writeValue(field.value, field.type);
this.writeValue(field.value);
});
}
}
function encodeEmbeddedNomsValue(v: valueOrPrimitive, t: Type, vw: ?ValueWriter): Chunk {
function encodeEmbeddedNomsValue(v: valueOrPrimitive, vw: ?ValueWriter): Chunk {
const w = new JsonArrayWriter(vw);
w.writeTopLevel(t, v);
w.writeValue(v);
return Chunk.fromString(typedTag + JSON.stringify(w.array));
}
@@ -308,7 +296,8 @@ function encodeTopLevelBlob(sequence: BlobLeafSequence): Chunk {
return new Chunk(data);
}
export function encodeNomsValue(v: valueOrPrimitive, t: Type, vw: ?ValueWriter): Chunk {
export function encodeNomsValue(v: valueOrPrimitive, vw: ?ValueWriter): Chunk {
const t = getTypeOfValue(v);
if (t.kind === Kind.Blob) {
invariant(v instanceof NomsBlob || v instanceof IndexedSequence);
const sequence = v instanceof NomsBlob ? v.sequence : v;
@@ -317,7 +306,7 @@ export function encodeNomsValue(v: valueOrPrimitive, t: Type, vw: ?ValueWriter):
return encodeTopLevelBlob(sequence);
}
}
return encodeEmbeddedNomsValue(v, t, vw);
return encodeEmbeddedNomsValue(v, vw);
}
setEncodeNomsValue(encodeNomsValue);
+3 -6
View File
@@ -5,24 +5,21 @@ import Ref from './ref.js';
import {assert} from 'chai';
import {ensureRef, getRef} from './get-ref.js';
import {Kind} from './noms-kind.js';
import {boolType} from './type.js';
import {suite, test} from 'mocha';
suite('get ref', () => {
test('getRef', () => {
const input = `t [${Kind.Bool},false]`;
const ref = Chunk.fromString(input).ref;
const tr = boolType;
const actual = getRef(false, tr);
const actual = getRef(false);
assert.strictEqual(ref.toString(), actual.toString());
});
test('ensureRef', () => {
let r: ?Ref = null;
const tr = boolType;
r = ensureRef(r, false, tr);
r = ensureRef(r, false);
assert.isNotNull(r);
assert.strictEqual(r, ensureRef(r, false, tr));
assert.strictEqual(r, ensureRef(r, false));
});
});
+5 -6
View File
@@ -4,12 +4,11 @@ import type Chunk from './chunk.js';
import type Ref from './ref.js';
import type {ValueWriter} from './value-store.js';
import {notNull} from './assert.js';
import type {Type} from './type.js';
import type {valueOrPrimitive} from './value.js';
import {getTypeOfValue} from './type.js';
import {Value} from './value.js';
type encodeFn = (v: valueOrPrimitive, t: Type, vw: ?ValueWriter) => Chunk;
type encodeFn = (v: valueOrPrimitive, vw: ?ValueWriter) => Chunk;
let encodeNomsValue: ?encodeFn = null;
export function getRefOfValue(v: valueOrPrimitive): Ref {
@@ -20,16 +19,16 @@ export function getRefOfValue(v: valueOrPrimitive): Ref {
return getRef(v, getTypeOfValue(v));
}
export function getRef(v: valueOrPrimitive, t: Type): Ref {
return notNull(encodeNomsValue)(v, t, null).ref;
export function getRef(v: valueOrPrimitive): Ref {
return notNull(encodeNomsValue)(v, null).ref;
}
export function ensureRef(r: ?Ref, v: valueOrPrimitive, t: Type): Ref {
export function ensureRef(r: ?Ref, v: valueOrPrimitive): Ref {
if (r !== null && r !== undefined && !r.isEmpty()) {
return r;
}
return getRef(v, t);
return getRef(v);
}
export function setEncodeNomsValue(encode: encodeFn) {
+4 -4
View File
@@ -30,7 +30,7 @@ import {invariant} from './assert.js';
import {ListLeafSequence, newList, NomsList} from './list.js';
const testListSize = 5000;
const listOfNRef = 'sha1-df0a58e5fb11b2bc0adbab07c2f39c6b3e02b42b';
const listOfNRef = 'sha1-9220f195a4273c1c31643014a6c6c6a39b2c068b';
async function assertToJS(list: NomsList, nums: Array<any>, start: number = 0,
end: number = nums.length): Promise<void> {
@@ -123,11 +123,11 @@ suite('List', () => {
}
test('List 1K', async () => {
await listTestSuite(10, 'sha1-12f9f864bfb61ae76ac3201f564757f1b576237c', 19, 19, 2);
await listTestSuite(10, 'sha1-34023a22fa32bda7d77c64c62361f3b31d674e6e', 19, 19, 2);
});
test('LONG: List 4K', async () => {
await listTestSuite(12, 'sha1-0bb374c248fcc987ef93dddef91af693032240a9', 2, 3, 2);
await listTestSuite(12, 'sha1-50389fd9a33c921c9aa7cc2b9b93290a13443cb4', 2, 3, 2);
});
test('LONG: list of ref, set of n numbers, length', async () => {
@@ -146,7 +146,7 @@ suite('List', () => {
});
const s = await newList(refs, tr);
assert.strictEqual(s.ref.toString(), 'sha1-477335cbd865c332b79db23eec5caaa4f8be3f45');
assert.strictEqual(s.ref.toString(), 'sha1-471aa3beb1f8d06a8a9a398c1b29fa34c0163ecd');
assert.strictEqual(testListSize, s.length);
});
+2 -2
View File
@@ -28,7 +28,7 @@ import type {Type} from './type.js';
import type {ValueReadWriter} from './value-store.js';
const testMapSize = 1000;
const mapOfNRef = 'sha1-67b979260f367f9a7e6ac8121eca87a2f5abd015';
const mapOfNRef = 'sha1-461888f373b08c62ee1744b873465666b5f239c0';
const smallRandomMapSize = 50;
const randomMapSize = 500;
@@ -114,7 +114,7 @@ suite('BuildMap', () => {
});
const m = await newMap(kvRefs, tr);
assert.strictEqual(m.ref.toString(), 'sha1-2784be4cfc759edbb89fcb57979d53d95d3e7187');
assert.strictEqual(m.ref.toString(), 'sha1-d38e77fb3de33e360976c245a86743e10091cb12');
});
test('LONG: set', async () => {
+3 -3
View File
@@ -29,7 +29,7 @@ import type {Type} from './type.js';
import type {ValueReadWriter} from './value-store.js';
const testSetSize = 5000;
const setOfNRef = 'sha1-5b4cd51d88b3d99e6dafdb1cafb8cec90d5aecdf';
const setOfNRef = 'sha1-189e35a1b7aa09e012c0a86f20921b4978d21629';
const smallRandomSetSize = 200;
const randomSetSize = 2000;
@@ -106,7 +106,7 @@ suite('BuildSet', () => {
});
const s = await newSet(refs, tr);
assert.strictEqual(s.ref.toString(), 'sha1-9d7c385651c1e58872621cf2b128f5107605c2c2');
assert.strictEqual(s.ref.toString(), 'sha1-d8815974c1b0ac51f2ffe8147d80ce8be8f5c52d');
});
@@ -119,7 +119,7 @@ suite('BuildSet', () => {
assert.strictEqual(i + 1, s.size);
}
assert.strictEqual(s.ref.toString(), 'sha1-ee27f104b663d852a3c6cb0fe23c9cf3f69e79c0');
assert.strictEqual(s.ref.toString(), 'sha1-0c2672150a517e593b118705e84ed438028902ff');
});
test('LONG: remove', async () => {
+1 -2
View File
@@ -8,7 +8,6 @@ import BatchStore from './batch-store.js';
import {BatchStoreAdaptorDelegate} from './batch-store-adaptor.js';
import ValueStore from './value-store.js';
import {newList} from './list.js';
import {stringType} from './type.js';
import {encodeNomsValue} from './encode.js';
export class FakeBatchStore extends BatchStore {
@@ -23,7 +22,7 @@ suite('ValueStore', () => {
const vs = new ValueStore(new FakeBatchStore(ms));
const input = 'abc';
const c = encodeNomsValue(input, stringType);
const c = encodeNomsValue(input);
const v1 = await vs.readValue(c.ref);
assert.equal(null, v1);
+1 -1
View File
@@ -71,7 +71,7 @@ export default class ValueStore {
writeValue<T: valueOrPrimitive>(v: T): RefValue<T> {
const t = getTypeOfValue(v);
const chunk = encodeNomsValue(v, t, this);
const chunk = encodeNomsValue(v, this);
invariant(!chunk.isEmpty());
const {ref} = chunk;
const refValue = refValueFromValue(v);
+1 -1
View File
@@ -18,7 +18,7 @@ export class Value {
}
get ref(): Ref {
return this._ref = ensureRef(this._ref, this, this.type);
return this._ref = ensureRef(this._ref, this);
}
equals(other: Value): boolean {
+6 -6
View File
@@ -75,26 +75,26 @@ func newBlobTestSuite(size uint, expectRefStr string, expectChunkCount int, expe
}
func TestBlobSuite1K(t *testing.T) {
suite.Run(t, newBlobTestSuite(10, "sha1-cb21e6231cbcf57ff8a9e80c9cbc5b1e798bf9ea", 3, 2, 2))
suite.Run(t, newBlobTestSuite(10, "sha1-28e2f80d426cdb8bdbb347d00050b4d3fcb644a8", 3, 2, 2))
}
func TestBlobSuite4K(t *testing.T) {
suite.Run(t, newBlobTestSuite(12, "sha1-53344f6e1d41ed9ce781e6cb3b999d3c5fc242a4", 9, 2, 2))
suite.Run(t, newBlobTestSuite(12, "sha1-5b2413e80d091f8b978ce927767e19e5655ac1a0", 9, 2, 2))
}
func TestBlobSuite16K(t *testing.T) {
suite.Run(t, newBlobTestSuite(14, "sha1-50821a3ce89449bbc490194000c380e979e79132", 33, 2, 2))
suite.Run(t, newBlobTestSuite(14, "sha1-666ebeed9cbcbcb2da71c0bd578c7266a5abf9b2", 33, 2, 2))
}
func TestBlobSuite64K(t *testing.T) {
suite.Run(t, newBlobTestSuite(16, "sha1-097098adc9ad9663c30ffcf69933b44165df1226", 4, 2, 2))
suite.Run(t, newBlobTestSuite(16, "sha1-a521ed352977cc544c2c98ac1a458f19fc551dce", 4, 2, 2))
}
func TestBlobSuite256K(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
suite.Run(t, newBlobTestSuite(18, "sha1-ff9c888571d2317bd201cfc2d31dbfd6a546c629", 13, 2, 2))
suite.Run(t, newBlobTestSuite(18, "sha1-4692cb536901b70e66109191b0091cfb2ed32eea", 2, 15, 2))
}
func (suite *blobTestSuite) TestRef() {
@@ -174,7 +174,7 @@ func chunkDiffCount(c1 []Ref, c2 []Ref) int {
refs := make(map[ref.Ref]int)
for _, r := range c1 {
refs[r.TargetRef()] += 1
refs[r.TargetRef()]++
}
for _, r := range c2 {
+2 -2
View File
@@ -664,7 +664,7 @@ func TestCompoundListFirstNNumbers(t *testing.T) {
nums := firstNNumbers(5000)
s := NewTypedList(listType, nums...)
assert.Equal("sha1-df0a58e5fb11b2bc0adbab07c2f39c6b3e02b42b", s.Ref().String())
assert.Equal("sha1-9220f195a4273c1c31643014a6c6c6a39b2c068b", s.Ref().String())
}
func TestCompoundListRefOfStructFirstNNumbers(t *testing.T) {
@@ -693,7 +693,7 @@ func TestCompoundListRefOfStructFirstNNumbers(t *testing.T) {
nums := firstNNumbers(5000)
s := NewTypedList(listType, nums...)
assert.Equal("sha1-477335cbd865c332b79db23eec5caaa4f8be3f45", s.Ref().String())
assert.Equal("sha1-471aa3beb1f8d06a8a9a398c1b29fa34c0163ecd", s.Ref().String())
}
func TestCompoundListModifyAfterRead(t *testing.T) {
+2 -2
View File
@@ -389,7 +389,7 @@ func TestCompoundMapFirstNNumbers(t *testing.T) {
}
m := NewTypedMap(mapType, kvs...)
assert.Equal("sha1-60f2d39d24da082cb8e022f866c60202152b2562", m.Ref().String())
assert.Equal("sha1-b6124b17659d88e0ac2a716e160403fab29f29b3", m.Ref().String())
}
func TestCompoundMapRefOfStructFirstNNumbers(t *testing.T) {
@@ -417,7 +417,7 @@ func TestCompoundMapRefOfStructFirstNNumbers(t *testing.T) {
}
m := NewTypedMap(mapType, kvs...)
assert.Equal("sha1-ea404a4f58d8d6afeacbc65f93edb26889d4ddd9", m.Ref().String())
assert.Equal("sha1-b968e56276f957e771b609416c18265ad7f93ede", m.Ref().String())
}
func TestCompoundMapModifyAfterRead(t *testing.T) {
+2 -2
View File
@@ -369,7 +369,7 @@ func TestCompoundSetFirstNNumbers(t *testing.T) {
nums := firstNNumbers(5000)
s := newTypedSet(setType, nums...)
assert.Equal("sha1-5b4cd51d88b3d99e6dafdb1cafb8cec90d5aecdf", s.Ref().String())
assert.Equal("sha1-189e35a1b7aa09e012c0a86f20921b4978d21629", s.Ref().String())
}
func TestCompoundSetRefOfStructFirstNNumbers(t *testing.T) {
@@ -398,7 +398,7 @@ func TestCompoundSetRefOfStructFirstNNumbers(t *testing.T) {
nums := firstNNumbers(5000)
s := NewTypedSet(setType, nums...)
assert.Equal("sha1-9d7c385651c1e58872621cf2b128f5107605c2c2", s.Ref().String())
assert.Equal("sha1-d8815974c1b0ac51f2ffe8147d80ce8be8f5c52d", s.Ref().String())
}
func TestCompoundSetModifyAfterRead(t *testing.T) {
+9 -24
View File
@@ -13,7 +13,7 @@ import (
func fromTypedEncodeable(i []interface{}, vr ValueReader) Value {
r := newJSONArrayReader(i, vr)
return r.readTopLevelValue()
return r.readValue()
}
type jsonArrayReader struct {
@@ -121,11 +121,9 @@ func (r *jsonArrayReader) readBlob() Value {
}
func (r *jsonArrayReader) readList(t *Type) Value {
desc := t.Desc.(CompoundDesc)
data := []Value{}
elemType := desc.ElemTypes[0]
for !r.atEnd() {
v := r.readValueWithoutTag(elemType)
v := r.readValue()
data = append(data, v)
}
@@ -133,11 +131,9 @@ func (r *jsonArrayReader) readList(t *Type) Value {
}
func (r *jsonArrayReader) readSet(t *Type) Value {
desc := t.Desc.(CompoundDesc)
data := setData{}
elemType := desc.ElemTypes[0]
for !r.atEnd() {
v := r.readValueWithoutTag(elemType)
v := r.readValue()
data = append(data, v)
}
@@ -145,14 +141,10 @@ func (r *jsonArrayReader) readSet(t *Type) Value {
}
func (r *jsonArrayReader) readMap(t *Type) Value {
desc := t.Desc.(CompoundDesc)
data := mapData{}
keyType := desc.ElemTypes[0]
valueType := desc.ElemTypes[1]
for !r.atEnd() {
k := r.readValueWithoutTag(keyType)
v := r.readValueWithoutTag(valueType)
k := r.readValue()
v := r.readValue()
data = append(data, mapEntry{k, v})
}
@@ -181,10 +173,9 @@ func (r *jsonArrayReader) maybeReadMetaSequence(t *Type) (Value, bool) {
r2 := newJSONArrayReader(r.readArray(), r.vr)
data := metaSequenceData{}
indexType := indexTypeForMetaSequence(t)
for !r2.atEnd() {
ref := NewTypedRef(MakeRefType(t), r2.readRef())
v := r2.readValueWithoutTag(indexType)
v := r2.readValue()
numLeaves := uint64(r2.readUint())
data = append(data, newMetaTuple(v, nil, ref, numLeaves))
}
@@ -197,12 +188,8 @@ func (r *jsonArrayReader) readRefValue(t *Type) Value {
return NewTypedRef(t, ref)
}
func (r *jsonArrayReader) readTopLevelValue() Value {
func (r *jsonArrayReader) readValue() Value {
t := r.readTypeAsTag(nil)
return r.readValueWithoutTag(t)
}
func (r *jsonArrayReader) readValueWithoutTag(t *Type) Value {
switch t.Kind() {
case BlobKind:
if ms, ok := r.maybeReadMetaSequence(t); ok {
@@ -217,9 +204,7 @@ func (r *jsonArrayReader) readValueWithoutTag(t *Type) Value {
case StringKind:
return NewString(r.readString())
case ValueKind:
// The value is always tagged
t := r.readTypeAsTag(nil)
return r.readValueWithoutTag(t)
return r.readValue()
case ListKind:
if ms, ok := r.maybeReadMetaSequence(t); ok {
return ms
@@ -283,7 +268,7 @@ func (r *jsonArrayReader) readStruct(t *Type) Value {
values := []Value{}
desc := t.Desc.(StructDesc)
desc.IterFields(func(name string, t *Type) {
values = append(values, r.readValueWithoutTag(t))
values = append(values, r.readValue())
})
return structBuilder(values, t)
+98 -48
View File
@@ -4,6 +4,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"regexp"
"strconv"
"strings"
"testing"
@@ -28,7 +30,27 @@ func TestRead(t *testing.T) {
assert.True(r.atEnd())
}
var replaceMap = map[string]NomsKind{
"BoolKind": BoolKind,
"NumberKind": NumberKind,
"StringKind": StringKind,
"BlobKind": BlobKind,
"ValueKind": ValueKind,
"ListKind": ListKind,
"MapKind": MapKind,
"RefKind": RefKind,
"SetKind": SetKind,
"StructKind": StructKind,
"TypeKind": TypeKind,
"ParentKind": ParentKind,
}
var kindRe = regexp.MustCompile(`(\w+Kind)`)
func parseJSON(s string, vs ...interface{}) (v []interface{}) {
s = kindRe.ReplaceAllStringFunc(s, func(word string) string {
i := replaceMap[word]
return strconv.Itoa(int(i))
})
dec := json.NewDecoder(strings.NewReader(fmt.Sprintf(s, vs...)))
dec.Decode(&v)
return
@@ -54,32 +76,32 @@ func TestReadPrimitives(t *testing.T) {
cs := NewTestValueStore()
test := func(expected Value, s string, vs ...interface{}) {
a := parseJSON(s, vs...)
test := func(expected Value, s string) {
a := parseJSON(s)
r := newJSONArrayReader(a, cs)
v := r.readTopLevelValue()
v := r.readValue()
assert.True(expected.Equals(v))
}
test(Bool(true), "[%d, true]", BoolKind)
test(Bool(false), "[%d, false]", BoolKind)
test(Number(0), `[%d, "0"]`, NumberKind)
test(NewString("hi"), `[%d, "hi"]`, StringKind)
test(Bool(true), "[BoolKind, true]")
test(Bool(false), "[BoolKind, false]")
test(Number(0), `[NumberKind, "0"]`)
test(NewString("hi"), `[StringKind, "hi"]`)
blob := NewBlob(bytes.NewBuffer([]byte{0x00, 0x01}))
test(blob, `[%d, false, "AAE="]`, BlobKind)
test(blob, `[BlobKind, false, "AAE="]`)
}
func TestReadListOfNumber(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, false, ["0", "1", "2", "3"]]`, ListKind, NumberKind)
a := parseJSON(`[ListKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`)
r := newJSONArrayReader(a, cs)
tr := MakeListType(NumberType)
l := r.readTopLevelValue()
l := r.readValue()
l2 := NewTypedList(tr, Number(0), Number(1), Number(2), Number(3))
assert.True(l2.Equals(l))
}
@@ -88,9 +110,9 @@ func TestReadListOfValue(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, false, [%d, "1", %d, "hi", %d, true]]`, ListKind, ValueKind, NumberKind, StringKind, BoolKind)
a := parseJSON(`[ListKind, ValueKind, false, [NumberKind, "1", StringKind, "hi", BoolKind, true]]`)
r := newJSONArrayReader(a, cs)
l := r.readTopLevelValue()
l := r.readValue()
assert.True(NewList(Number(1), NewString("hi"), Bool(true)).Equals(l))
}
@@ -98,12 +120,12 @@ func TestReadValueListOfNumber(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, %d, false, ["0", "1", "2"]]`, ValueKind, ListKind, NumberKind)
a := parseJSON(`[ValueKind, ListKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2"]]`)
r := newJSONArrayReader(a, cs)
tr := MakeListType(NumberType)
l := r.readTopLevelValue()
l := r.readValue()
l2 := NewTypedList(tr, Number(0), Number(1), Number(2))
assert.True(l2.Equals(l))
}
@@ -120,9 +142,9 @@ func TestReadCompoundList(t *testing.T) {
newMetaTuple(Number(4), leaf2, Ref{}, 4),
}, tr, cs)
a := parseJSON(`[%d, %d, true, ["%s", "1", "1", "%s", "4", "4"]]`, ListKind, NumberKind, leaf1.Ref(), leaf2.Ref())
a := parseJSON(`[ListKind, NumberKind, true, ["%s", NumberKind, "1", "1", "%s", NumberKind, "4", "4"]]`, leaf1.Ref(), leaf2.Ref())
r := newJSONArrayReader(a, cs)
l := r.readTopLevelValue()
l := r.readValue()
assert.True(l2.Equals(l))
}
@@ -139,9 +161,9 @@ func TestReadCompoundSet(t *testing.T) {
newMetaTuple(Number(4), leaf2, Ref{}, 3),
}, tr, cs)
a := parseJSON(`[%d, %d, true, ["%s", "1", "2", "%s", "4", "3"]]`, SetKind, NumberKind, leaf1.Ref(), leaf2.Ref())
a := parseJSON(`[SetKind, NumberKind, true, ["%s", NumberKind, "1", "2", "%s", NumberKind, "4", "3"]]`, leaf1.Ref(), leaf2.Ref())
r := newJSONArrayReader(a, cs)
l := r.readTopLevelValue()
l := r.readValue()
assert.True(l2.Equals(l))
}
@@ -150,12 +172,12 @@ func TestReadMapOfNumberToNumber(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, %d, false, ["0", "1", "2", "3"]]`, MapKind, NumberKind, NumberKind)
a := parseJSON(`[MapKind, NumberKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`)
r := newJSONArrayReader(a, cs)
tr := MakeMapType(NumberType, NumberType)
m := r.readTopLevelValue()
m := r.readValue()
m2 := NewTypedMap(tr, Number(0), Number(1), Number(2), Number(3))
assert.True(m2.Equals(m))
}
@@ -164,12 +186,12 @@ func TestReadValueMapOfNumberToNumber(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, %d, %d, false, ["0", "1", "2", "3"]]`, ValueKind, MapKind, NumberKind, NumberKind)
a := parseJSON(`[ValueKind, MapKind, NumberKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`)
r := newJSONArrayReader(a, cs)
tr := MakeMapType(NumberType, NumberType)
m := r.readTopLevelValue()
m := r.readValue()
m2 := NewTypedMap(tr, Number(0), Number(1), Number(2), Number(3))
assert.True(m2.Equals(m))
}
@@ -178,12 +200,12 @@ func TestReadSetOfNumber(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, false, ["0", "1", "2", "3"]]`, SetKind, NumberKind)
a := parseJSON(`[SetKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`)
r := newJSONArrayReader(a, cs)
tr := MakeSetType(NumberType)
s := r.readTopLevelValue()
s := r.readValue()
s2 := NewTypedSet(tr, Number(0), Number(1), Number(2), Number(3))
assert.True(s2.Equals(s))
}
@@ -192,12 +214,12 @@ func TestReadValueSetOfNumber(t *testing.T) {
assert := assert.New(t)
cs := NewTestValueStore()
a := parseJSON(`[%d, %d, %d, false, ["0", "1", "2", "3"]]`, ValueKind, SetKind, NumberKind)
a := parseJSON(`[ValueKind, SetKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"]]`)
r := newJSONArrayReader(a, cs)
setTr := MakeSetType(NumberType)
s := r.readTopLevelValue()
s := r.readValue()
s2 := NewTypedSet(setTr, Number(0), Number(1), Number(2), Number(3))
assert.True(s2.Equals(s))
}
@@ -209,10 +231,10 @@ func TestReadCompoundBlob(t *testing.T) {
r1 := ref.Parse("sha1-0000000000000000000000000000000000000001")
r2 := ref.Parse("sha1-0000000000000000000000000000000000000002")
r3 := ref.Parse("sha1-0000000000000000000000000000000000000003")
a := parseJSON(`[%d, true, ["%s", "20", "20", "%s", "40", "40", "%s", "60", "60"]]`, BlobKind, r1, r2, r3)
a := parseJSON(`[BlobKind, true, ["%s", NumberKind, "20", "20", "%s", NumberKind, "40", "40", "%s", NumberKind, "60", "60"]]`, r1, r2, r3)
r := newJSONArrayReader(a, cs)
m := r.readTopLevelValue()
m := r.readValue()
_, ok := m.(compoundBlob)
assert.True(ok)
m2 := newCompoundBlob([]metaTuple{
@@ -235,10 +257,10 @@ func TestReadStruct(t *testing.T) {
"b": BoolType,
})
a := parseJSON(`[%d, "A1", ["b", %d, "s", %d, "x", %d], true, "hi", "42"]`, StructKind, BoolKind, StringKind, NumberKind)
a := parseJSON(`[StructKind, "A1", ["b", BoolKind, "s", StringKind, "x", NumberKind], BoolKind, true, StringKind, "hi", NumberKind, "42"]`)
r := newJSONArrayReader(a, cs)
v := r.readTopLevelValue().(Struct)
v := r.readValue().(Struct)
assert.True(v.Type().Equals(typ))
assert.True(v.Get("x").Equals(Number(42)))
assert.True(v.Get("s").Equals(NewString("hi")))
@@ -261,10 +283,10 @@ func TestReadStructWithList(t *testing.T) {
"s": StringType,
})
a := parseJSON(`[%d, "A4", ["b", %d, "l", %d, %d, "s", %d], true, false, ["0", "1", "2"], "hi"]`, StructKind, BoolKind, ListKind, NumberKind, StringKind)
a := parseJSON(`[StructKind, "A4", ["b", BoolKind, "l", ListKind, NumberKind, "s", StringKind], BoolKind, true, ListKind, NumberKind, false, [NumberKind, "0", NumberKind, "1", NumberKind, "2"], StringKind, "hi"]`)
r := newJSONArrayReader(a, cs)
l32Tr := MakeListType(NumberType)
v := r.readTopLevelValue().(Struct)
v := r.readValue().(Struct)
assert.True(v.Type().Equals(typ))
assert.True(v.Get("b").Equals(Bool(true)))
@@ -289,9 +311,9 @@ func TestReadStructWithValue(t *testing.T) {
"s": StringType,
})
a := parseJSON(`[%d, "A5", ["b", %d, "s", %d, "v", %d], true, "hi", %d, "42"]`, StructKind, BoolKind, StringKind, ValueKind, NumberKind)
a := parseJSON(`[StructKind, "A5", ["b", BoolKind, "s", StringKind, "v", ValueKind], BoolKind, true, StringKind, "hi", NumberKind, "42"]`)
r := newJSONArrayReader(a, cs)
v := r.readTopLevelValue().(Struct)
v := r.readValue().(Struct)
assert.True(v.Type().Equals(typ))
assert.True(v.Get("b").Equals(Bool(true)))
@@ -315,9 +337,9 @@ func TestReadValueStruct(t *testing.T) {
"b": BoolType,
})
a := parseJSON(`[%d, %d, "A1", ["b", %d, "s", %d, "x", %d], true, "hi", "42"]`, ValueKind, StructKind, BoolKind, StringKind, NumberKind)
a := parseJSON(`[ValueKind, StructKind, "A1", ["b", BoolKind, "s", StringKind, "x", NumberKind], BoolKind, true, StringKind, "hi", NumberKind, "42"]`)
r := newJSONArrayReader(a, cs)
v := r.readTopLevelValue().(Struct)
v := r.readValue().(Struct)
assert.True(v.Type().Equals(typ))
assert.True(v.Get("x").Equals(Number(42)))
@@ -332,7 +354,7 @@ func TestReadRef(t *testing.T) {
r := ref.Parse("sha1-a9993e364706816aba3e25717850c26c9cd0d89d")
a := parseJSON(`[%d, %d, "%s"]`, RefKind, NumberKind, r.String())
reader := newJSONArrayReader(a, cs)
v := reader.readTopLevelValue()
v := reader.readValue()
tr := MakeRefType(NumberType)
assert.True(NewTypedRef(tr, r).Equals(v))
}
@@ -344,7 +366,7 @@ func TestReadValueRef(t *testing.T) {
r := ref.Parse("sha1-a9993e364706816aba3e25717850c26c9cd0d89d")
a := parseJSON(`[%d, %d, %d, "%s"]`, ValueKind, RefKind, NumberKind, r.String())
reader := newJSONArrayReader(a, cs)
v := reader.readTopLevelValue()
v := reader.readValue()
tr := MakeRefType(NumberType)
assert.True(NewTypedRef(tr, r).Equals(v))
}
@@ -361,9 +383,9 @@ func TestReadStructWithBlob(t *testing.T) {
"b": BlobType,
})
a := parseJSON(`[%d, "A5", ["b", %d], false, "AAE="]`, StructKind, BlobKind)
a := parseJSON(`[StructKind, "A5", ["b", BlobKind], BlobKind, false, "AAE="]`)
r := newJSONArrayReader(a, cs)
v := r.readTopLevelValue().(Struct)
v := r.readValue().(Struct)
assert.True(v.Type().Equals(typ))
blob := NewBlob(bytes.NewBuffer([]byte{0x00, 0x01}))
assert.True(v.Get("b").Equals(blob))
@@ -390,18 +412,46 @@ func TestReadRecursiveStruct(t *testing.T) {
at.Desc.(StructDesc).Fields["b"] = bt
bt.Desc.(StructDesc).Fields["b"] = MakeListType(bt)
a := parseJSON(`[%d, "A",
["b", %d, "B", [
"a", %d, %d, 1,
"b", %d, %d, 0
]],
false, [], false, []]`, StructKind, StructKind, ListKind, ParentKind, ListKind, ParentKind)
// {b: {a: [], b: []}}
v2 := NewStruct(at, structData{
"b": NewStruct(bt, structData{
"a": NewTypedList(MakeListType(at)),
"b": NewTypedList(MakeListType(bt)),
}),
})
a := parseJSON(`[
StructKind, "A", [
"b", StructKind, "B", [
"a", ListKind, ParentKind, 1,
"b", ListKind, ParentKind, 0
]
],
StructKind, "B", [
"a", ListKind, StructKind, "A", [
"b", ParentKind, 1
],
"b", ListKind, ParentKind, 0
],
ListKind, StructKind, "A", [
"b", StructKind, "B", [
"a", ListKind, ParentKind, 1,
"b", ListKind, ParentKind, 0
]
], false, [],
ListKind, StructKind, "B", [
"a", ListKind, StructKind, "A", [
"b", ParentKind, 1
],
"b", ListKind, ParentKind, 0
], false, []]`)
r := newJSONArrayReader(a, cs)
v := r.readTopLevelValue().(Struct)
v := r.readValue().(Struct)
assert.True(v.Type().Equals(at))
assert.True(v.Get("b").Type().Equals(bt))
assert.True(v.Equals(v2))
}
func TestReadTypeValue(t *testing.T) {
@@ -411,7 +461,7 @@ func TestReadTypeValue(t *testing.T) {
test := func(expected *Type, json string, vs ...interface{}) {
a := parseJSON(json, vs...)
r := newJSONArrayReader(a, cs)
tr := r.readTopLevelValue()
tr := r.readValue()
assert.True(expected.Equals(tr))
}
+25 -34
View File
@@ -8,12 +8,11 @@ import (
"strings"
"github.com/attic-labs/noms/d"
"github.com/attic-labs/noms/ref"
)
func encNomsValue(v Value, vw ValueWriter) []interface{} {
w := newJSONArrayWriter(vw)
w.writeTopLevelValue(v)
w.writeValue(v)
return w.toArray()
}
@@ -58,12 +57,16 @@ func (w *jsonArrayWriter) writeUint8(v uint8) {
w.write(v)
}
func (w *jsonArrayWriter) writeKind(kind NomsKind) {
w.write(kind)
}
func (w *jsonArrayWriter) toArray() []interface{} {
return w.a
}
func (w *jsonArrayWriter) writeRef(r ref.Ref) {
w.write(r.String())
func (w *jsonArrayWriter) writeRef(r Ref) {
w.write(r.TargetRef().String())
}
func (w *jsonArrayWriter) writeTypeAsTag(t *Type, parentStructTypes []*Type) {
@@ -81,12 +84,6 @@ func (w *jsonArrayWriter) writeTypeAsTag(t *Type, parentStructTypes []*Type) {
}
}
func (w *jsonArrayWriter) writeTopLevelValue(v Value) {
tr := v.Type()
w.writeTypeAsTag(tr, nil)
w.writeValue(v, tr)
}
func (w *jsonArrayWriter) maybeWriteMetaSequence(v Value, tr *Type) bool {
ms, ok := v.(metaSequence)
if !ok {
@@ -96,24 +93,25 @@ func (w *jsonArrayWriter) maybeWriteMetaSequence(v Value, tr *Type) bool {
w.write(true) // a meta sequence
w2 := newJSONArrayWriter(w.vw)
indexType := indexTypeForMetaSequence(tr)
for _, tuple := range ms.(metaSequence).data() {
if tuple.child != nil && w.vw != nil {
// Write unwritten chunked sequences. Chunks are lazily written so that intermediate chunked structures like NewList().Append(x).Append(y) don't cause unnecessary churn.
w.vw.WriteValue(tuple.child)
}
w2.writeRef(tuple.ChildRef().TargetRef())
w2.writeValue(tuple.value, indexType)
w2.writeRef(tuple.ChildRef())
w2.writeValue(tuple.value)
w2.writeUint(tuple.numLeaves)
}
w.write(w2.toArray())
return true
}
func (w *jsonArrayWriter) writeValue(v Value, tr *Type) {
switch tr.Kind() {
func (w *jsonArrayWriter) writeValue(v Value) {
t := v.Type()
w.writeTypeAsTag(t, nil)
switch t.Kind() {
case BlobKind:
if w.maybeWriteMetaSequence(v, tr) {
if w.maybeWriteMetaSequence(v, t) {
return
}
w.writeBlob(v.(Blob))
@@ -122,39 +120,36 @@ func (w *jsonArrayWriter) writeValue(v Value, tr *Type) {
case NumberKind:
w.writeFloat(float64(v.(Number)))
case ListKind:
if w.maybeWriteMetaSequence(v, tr) {
if w.maybeWriteMetaSequence(v, t) {
return
}
w2 := newJSONArrayWriter(w.vw)
elemType := tr.Desc.(CompoundDesc).ElemTypes[0]
v.(List).IterAll(func(v Value, i uint64) {
w2.writeValue(v, elemType)
w2.writeValue(v)
})
w.write(w2.toArray())
case MapKind:
if w.maybeWriteMetaSequence(v, tr) {
if w.maybeWriteMetaSequence(v, t) {
return
}
w2 := newJSONArrayWriter(w.vw)
elemTypes := tr.Desc.(CompoundDesc).ElemTypes
v.(Map).IterAll(func(k, v Value) {
w2.writeValue(k, elemTypes[0])
w2.writeValue(v, elemTypes[1])
w2.writeValue(k)
w2.writeValue(v)
})
w.write(w2.toArray())
case RefKind:
w.writeRef(v.(Ref).TargetRef())
w.writeRef(v.(Ref))
case SetKind:
if w.maybeWriteMetaSequence(v, tr) {
if w.maybeWriteMetaSequence(v, t) {
return
}
w2 := newJSONArrayWriter(w.vw)
elemType := tr.Desc.(CompoundDesc).ElemTypes[0]
v.(Set).IterAll(func(v Value) {
w2.writeValue(v, elemType)
w2.writeValue(v)
})
w.write(w2.toArray())
case StringKind:
@@ -163,12 +158,8 @@ func (w *jsonArrayWriter) writeValue(v Value, tr *Type) {
vt := v.(*Type)
w.writeTypeAsValue(vt, nil)
case StructKind:
w.writeStruct(v, tr)
case ValueKind:
vt := v.Type()
w.writeTypeAsTag(vt, nil)
w.writeValue(v, v.Type())
case ParentKind:
w.writeStruct(v, t)
case ValueKind, ParentKind:
default:
d.Chk.Fail("Unknown NomsKind")
}
@@ -241,7 +232,7 @@ func (w *jsonArrayWriter) writeStruct(v Value, t *Type) {
i := 0
desc.IterFields(func(name string, t *Type) {
w.writeValue(values[i], t)
w.writeValue(values[i])
i++
})
}
+83 -44
View File
@@ -14,7 +14,7 @@ func TestWritePrimitives(t *testing.T) {
f := func(k NomsKind, v Value, ex interface{}) {
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
assert.EqualValues([]interface{}{k, ex}, w.toArray())
}
@@ -33,7 +33,7 @@ func TestWritePrimitives(t *testing.T) {
func TestWriteSimpleBlob(t *testing.T) {
assert := assert.New(t)
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(NewBlob(bytes.NewBuffer([]byte{0x00, 0x01})))
w.writeValue(NewBlob(bytes.NewBuffer([]byte{0x00, 0x01})))
assert.EqualValues([]interface{}{BlobKind, false, "AAE="}, w.toArray())
}
@@ -44,8 +44,8 @@ func TestWriteList(t *testing.T) {
v := NewTypedList(typ, Number(0), Number(1), Number(2), Number(3))
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{ListKind, NumberKind, false, []interface{}{"0", "1", "2", "3"}}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{ListKind, NumberKind, false, []interface{}{NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"}}, w.toArray())
}
func TestWriteListOfList(t *testing.T) {
@@ -58,8 +58,11 @@ func TestWriteListOfList(t *testing.T) {
v := NewTypedList(typ, l1, l2)
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{ListKind, ListKind, NumberKind, false, []interface{}{false, []interface{}{"0"}, false, []interface{}{"1", "2", "3"}}}, w.toArray())
w.writeValue(v)
// List<List<Number>([[0], [1, 2, 3]])
assert.EqualValues([]interface{}{ListKind, ListKind, NumberKind, false, []interface{}{
ListKind, NumberKind, false, []interface{}{NumberKind, "0"},
ListKind, NumberKind, false, []interface{}{NumberKind, "1", NumberKind, "2", NumberKind, "3"}}}, w.toArray())
}
func TestWriteSet(t *testing.T) {
@@ -69,9 +72,9 @@ func TestWriteSet(t *testing.T) {
v := NewTypedSet(typ, Number(3), Number(1), Number(2), Number(0))
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
// The order of the elements is based on the order defined by OrderedValue.
assert.EqualValues([]interface{}{SetKind, NumberKind, false, []interface{}{"0", "1", "2", "3"}}, w.toArray())
assert.EqualValues([]interface{}{SetKind, NumberKind, false, []interface{}{NumberKind, "0", NumberKind, "1", NumberKind, "2", NumberKind, "3"}}, w.toArray())
}
func TestWriteSetOfSet(t *testing.T) {
@@ -82,9 +85,11 @@ func TestWriteSetOfSet(t *testing.T) {
v := NewTypedSet(typ, NewTypedSet(st, Number(0)), NewTypedSet(st, Number(1), Number(2), Number(3)))
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
// The order of the elements is based on the order defined by OrderedValue.
assert.EqualValues([]interface{}{SetKind, SetKind, NumberKind, false, []interface{}{false, []interface{}{"0"}, false, []interface{}{"1", "2", "3"}}}, w.toArray())
assert.EqualValues([]interface{}{SetKind, SetKind, NumberKind, false, []interface{}{
SetKind, NumberKind, false, []interface{}{NumberKind, "1", NumberKind, "2", NumberKind, "3"},
SetKind, NumberKind, false, []interface{}{NumberKind, "0"}}}, w.toArray())
}
func TestWriteMap(t *testing.T) {
@@ -94,23 +99,28 @@ func TestWriteMap(t *testing.T) {
v := newMapLeaf(typ, mapEntry{NewString("a"), Bool(false)}, mapEntry{NewString("b"), Bool(true)})
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
// The order of the elements is based on the order defined by OrderedValue.
assert.EqualValues([]interface{}{MapKind, StringKind, BoolKind, false, []interface{}{"a", false, "b", true}}, w.toArray())
assert.EqualValues([]interface{}{MapKind, StringKind, BoolKind, false, []interface{}{
StringKind, "a", BoolKind, false, StringKind, "b", BoolKind, true}}, w.toArray())
}
func TestWriteMapOfMap(t *testing.T) {
assert := assert.New(t)
// Map<Map<String, Number>, Set<Bool>>
kt := MakeMapType(StringType, NumberType)
vt := MakeSetType(BoolType)
typ := MakeMapType(kt, vt)
// { {"a": 0}: {true} }
v := NewTypedMap(typ, NewTypedMap(kt, NewString("a"), Number(0)), NewTypedSet(vt, Bool(true)))
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
// the order of the elements is based on the ref of the value.
assert.EqualValues([]interface{}{MapKind, MapKind, StringKind, NumberKind, SetKind, BoolKind, false, []interface{}{false, []interface{}{"a", "0"}, false, []interface{}{true}}}, w.toArray())
assert.EqualValues([]interface{}{MapKind, MapKind, StringKind, NumberKind, SetKind, BoolKind, false, []interface{}{
MapKind, StringKind, NumberKind, false, []interface{}{StringKind, "a", NumberKind, "0"},
SetKind, BoolKind, false, []interface{}{BoolKind, true}}}, w.toArray())
}
func TestWriteCompoundBlob(t *testing.T) {
@@ -126,10 +136,10 @@ func TestWriteCompoundBlob(t *testing.T) {
newMetaTuple(Number(60), nil, NewTypedRef(RefOfBlobType, r3), 60),
}, NewTestValueStore())
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
// the order of the elements is based on the ref of the value.
assert.EqualValues([]interface{}{BlobKind, true, []interface{}{r1.String(), "20", "20", r2.String(), "40", "40", r3.String(), "60", "60"}}, w.toArray())
assert.EqualValues([]interface{}{BlobKind, true, []interface{}{r1.String(), NumberKind, "20", "20", r2.String(), NumberKind, "40", "40", r3.String(), NumberKind, "60", "60"}}, w.toArray())
}
func TestWriteEmptyStruct(t *testing.T) {
@@ -139,7 +149,7 @@ func TestWriteEmptyStruct(t *testing.T) {
v := NewStruct(typ, nil)
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{}}, w.toArray())
}
@@ -152,27 +162,33 @@ func TestWriteStruct(t *testing.T) {
})
v := NewStruct(typ, structData{"x": Number(42), "b": Bool(true)})
// struct S {x: Number, b: Bool}({x: 42, b: true})
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"b", BoolKind, "x", NumberKind}, true, "42"}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"b", BoolKind, "x", NumberKind}, BoolKind, true, NumberKind, "42"}, w.toArray())
}
func TestWriteStructWithList(t *testing.T) {
assert := assert.New(t)
listType := MakeListType(StringType)
typ := MakeStructType("S", TypeMap{
"l": MakeListType(StringType),
"l": listType,
})
v := NewStruct(typ, structData{"l": NewList(NewString("a"), NewString("b"))})
// struct S {l: List<String>}({l: ["a", "b"]})
v := NewStruct(typ, structData{"l": NewTypedList(listType, NewString("a"), NewString("b"))})
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"l", ListKind, StringKind}, false, []interface{}{"a", "b"}}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"l", ListKind, StringKind},
ListKind, StringKind, false, []interface{}{StringKind, "a", StringKind, "b"}}, w.toArray())
v = NewStruct(typ, structData{"l": NewList()})
// struct S {l: List<String>}({l: []})
v = NewStruct(typ, structData{"l": NewTypedList(listType)})
w = newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"l", ListKind, StringKind}, false, []interface{}{}}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"l", ListKind, StringKind},
ListKind, StringKind, false, []interface{}{}}, w.toArray())
}
func TestWriteStructWithStruct(t *testing.T) {
@@ -194,10 +210,11 @@ func TestWriteStructWithStruct(t *testing.T) {
}),
})
// {s: {x: 42}}
v := NewStruct(sType, structData{"s": NewStruct(s2Type, structData{"x": Number(42)})})
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"s", StructKind, "S2", []interface{}{"x", NumberKind}}, "42"}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"s", StructKind, "S2", []interface{}{"x", NumberKind}}, StructKind, "S2", []interface{}{"x", NumberKind}, NumberKind, "42"}, w.toArray())
}
func TestWriteStructWithBlob(t *testing.T) {
@@ -210,8 +227,8 @@ func TestWriteStructWithBlob(t *testing.T) {
v := NewStruct(typ, structData{"b": b})
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"b", BlobKind}, false, "AAE="}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{StructKind, "S", []interface{}{"b", BlobKind}, BlobKind, false, "AAE="}, w.toArray())
}
func TestWriteCompoundList(t *testing.T) {
@@ -226,8 +243,8 @@ func TestWriteCompoundList(t *testing.T) {
}, ltr, NewTestValueStore())
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(cl)
assert.EqualValues([]interface{}{ListKind, NumberKind, true, []interface{}{leaf1.Ref().String(), "1", "1", leaf2.Ref().String(), "4", "4"}}, w.toArray())
w.writeValue(cl)
assert.EqualValues([]interface{}{ListKind, NumberKind, true, []interface{}{leaf1.Ref().String(), NumberKind, "1", "1", leaf2.Ref().String(), NumberKind, "4", "4"}}, w.toArray())
}
func TestWriteCompoundSet(t *testing.T) {
@@ -242,8 +259,8 @@ func TestWriteCompoundSet(t *testing.T) {
}, ltr, NewTestValueStore())
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(cl)
assert.EqualValues([]interface{}{SetKind, NumberKind, true, []interface{}{leaf1.Ref().String(), "1", "2", leaf2.Ref().String(), "4", "3"}}, w.toArray())
w.writeValue(cl)
assert.EqualValues([]interface{}{SetKind, NumberKind, true, []interface{}{leaf1.Ref().String(), NumberKind, "1", "2", leaf2.Ref().String(), NumberKind, "4", "3"}}, w.toArray())
}
func TestWriteListOfValue(t *testing.T) {
@@ -259,7 +276,7 @@ func TestWriteListOfValue(t *testing.T) {
)
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
assert.EqualValues([]interface{}{ListKind, ValueKind, false, []interface{}{
BoolKind, true,
@@ -278,9 +295,11 @@ func TestWriteListOfValueWithStruct(t *testing.T) {
listType := MakeListType(ValueType)
v := NewTypedList(listType, NewStruct(structType, structData{"x": Number(42)}))
// List<struct S {x: Number}>([{x: 42}])
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{ListKind, ValueKind, false, []interface{}{StructKind, "S", []interface{}{"x", NumberKind}, "42"}}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{ListKind, ValueKind, false, []interface{}{
StructKind, "S", []interface{}{"x", NumberKind}, NumberKind, "42"}}, w.toArray())
}
func TestWriteListOfValueWithType(t *testing.T) {
@@ -299,7 +318,7 @@ func TestWriteListOfValueWithType(t *testing.T) {
)
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
assert.EqualValues([]interface{}{ListKind, ValueKind, false, []interface{}{
BoolKind, true,
TypeKind, NumberKind,
@@ -315,7 +334,7 @@ func TestWriteRef(t *testing.T) {
v := NewTypedRef(typ, r)
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
assert.EqualValues([]interface{}{RefKind, NumberKind, r.String()}, w.toArray())
}
@@ -324,7 +343,7 @@ func TestWriteTypeValue(t *testing.T) {
test := func(expected []interface{}, v *Type) {
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
w.writeValue(v)
assert.EqualValues(expected, w.toArray())
}
@@ -347,9 +366,10 @@ func TestWriteListOfTypes(t *testing.T) {
typ := MakeListType(TypeType)
v := NewTypedList(typ, BoolType, StringType)
// List<Type>([Bool, String])
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{ListKind, TypeKind, false, []interface{}{BoolKind, StringKind}}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{ListKind, TypeKind, false, []interface{}{TypeKind, BoolKind, TypeKind, StringKind}}, w.toArray())
}
func TestWriteRecursiveStruct(t *testing.T) {
@@ -371,6 +391,7 @@ func TestWriteRecursiveStruct(t *testing.T) {
NewTypedList(listType)
// {v: 42, cs: [{v: 555, cs: []}]}
v := NewStruct(structType, structData{
"v": Number(42),
"cs": NewTypedList(listType, NewStruct(structType, structData{
@@ -380,6 +401,24 @@ func TestWriteRecursiveStruct(t *testing.T) {
})
w := newJSONArrayWriter(NewTestValueStore())
w.writeTopLevelValue(v)
assert.EqualValues([]interface{}{StructKind, "A6", []interface{}{"cs", ListKind, ParentKind, uint8(0), "v", NumberKind}, false, []interface{}{false, []interface{}{}, "555"}, "42"}, w.toArray())
w.writeValue(v)
assert.EqualValues([]interface{}{
StructKind, "A6", []interface{}{
"cs", ListKind, ParentKind, uint8(0),
"v", NumberKind,
},
ListKind, StructKind, "A6", []interface{}{
"cs", ListKind, ParentKind, uint8(0),
"v", NumberKind,
}, false, []interface{}{
StructKind, "A6", []interface{}{
"cs", ListKind, ParentKind, uint8(0),
"v", NumberKind,
}, ListKind, StructKind, "A6", []interface{}{
"cs", ListKind, ParentKind, uint8(0),
"v", NumberKind,
}, false, []interface{}{}, NumberKind, "555",
}, NumberKind, "42",
}, w.toArray())
}