Implement Enum encode/decode + a bunch of tests

This commit is contained in:
Rafael Weinstein
2015-11-24 23:12:19 -08:00
parent 9e9b57b00e
commit f3774020f5
5 changed files with 315 additions and 29 deletions
+13 -3
View File
@@ -6,7 +6,7 @@ import Struct from './struct.js';
import type {ChunkStore} from './chunk_store.js';
import type {NomsKind} from './noms_kind.js';
import {decode as decodeBase64} from './base64.js';
import {Field, makeCompoundType, makePrimitiveType, makeStructType, makeType, makeUnresolvedType, StructDesc, Type} from './type.js';
import {Field, makeCompoundType, makeEnumType, makePrimitiveType, makeStructType, makeType, makeUnresolvedType, StructDesc, Type} from './type.js';
import {invariant, notNull} from './assert.js';
import {isPrimitiveKind, Kind} from './noms_kind.js';
import {lookupPackage, Package, readPackage} from './package.js';
@@ -134,6 +134,10 @@ class JsonArrayReader {
return m;
}
readEnum(): number {
return this.readNumber();
}
readPackage(t: Type, pkg: ?Package): Package {
let r2 = new JsonArrayReader(this.readArray(), this._cs);
let types = [];
@@ -222,7 +226,7 @@ class JsonArrayReader {
pkg = notNull(pkg);
let typeDef = pkg.types[ordinal];
if (typeDef.kind === Kind.Enum) {
throw new Error('Not implemented');
return this.readEnum();
}
invariant(typeDef.kind === Kind.Struct);
@@ -234,7 +238,13 @@ class JsonArrayReader {
switch (k) {
case Kind.Enum:
throw new Error('Not implemented');
let name = this.readString();
let r2 = new JsonArrayReader(this.readArray(), this._cs);
let ids = [];
while (!r2.atEnd()) {
ids.push(r2.readString());
}
return makeEnumType(name, ids);
case Kind.List:
case Kind.Map:
case Kind.Ref:
+161 -2
View File
@@ -8,7 +8,7 @@ import test from './async_test.js';
import type {TypeDesc} from './type.js';
import {assert} from 'chai';
import {decodeNomsValue, JsonArrayReader, readValue} from './decode.js';
import {Field, makeCompoundType, makePrimitiveType, makeStructType, makeType, Type} from './type.js';
import {Field, makeCompoundType, makeEnumType, makePrimitiveType, makeStructType, makeType, Type} from './type.js';
import {invariant} from './assert.js';
import {Kind} from './noms_kind.js';
import {registerPackage, Package} from './package.js';
@@ -172,7 +172,7 @@ suite('Decode', () => {
assert.deepEqual(desc, s.desc);
for (let key in data) {
assert.strictEqual(data[key], s.get(key));
assert.deepEqual(data[key], s.get(key));
}
}
@@ -198,6 +198,165 @@ suite('Decode', () => {
});
});
test('test read struct union', async () => {
let ms = new MemoryStore();
let tr = makeStructType('A2', [
new Field('x', makePrimitiveType(Kind.Float32), false)
], [
new Field('b', makePrimitiveType(Kind.Bool), false),
new Field('s', makePrimitiveType(Kind.String), false)
]);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Unresolved, pkg.ref.toString(), 0, 42, 1, 'hi'];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assertStruct(v, tr.desc, {
x: 42,
s: 'hi'
});
});
test('test read struct optional', async () => {
let ms = new MemoryStore();
let tr = makeStructType('A3', [
new Field('x', makePrimitiveType(Kind.Float32), false),
new Field('s', makePrimitiveType(Kind.String), true),
new Field('b', makePrimitiveType(Kind.Bool), true)
], []);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Unresolved, pkg.ref.toString(), 0, 42, false, true, false];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assertStruct(v, tr.desc, {
x: 42,
b: false
});
});
test('test read struct with list', async () => {
let ms = new MemoryStore();
let tr = makeStructType('A4', [
new Field('b', makePrimitiveType(Kind.Bool), false),
new Field('l', makeCompoundType(Kind.List, makePrimitiveType(Kind.Int32)), false),
new Field('s', makePrimitiveType(Kind.String), false)
], []);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Unresolved, pkg.ref.toString(), 0, true, [0, 1, 2], 'hi'];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assertStruct(v, tr.desc, {
b: true,
l: [0, 1, 2],
s: 'hi'
});
});
test('test read struct with value', async () => {
let ms = new MemoryStore();
let tr = makeStructType('A5', [
new Field('b', makePrimitiveType(Kind.Bool), false),
new Field('v', makePrimitiveType(Kind.Value), false),
new Field('s', makePrimitiveType(Kind.String), false)
], []);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Unresolved, pkg.ref.toString(), 0, true, Kind.UInt8, 42, 'hi'];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assertStruct(v, tr.desc, {
b: true,
v: 42,
s: 'hi'
});
});
test('test read value struct', async () => {
let ms = new MemoryStore();
let tr = makeStructType('A1', [
new Field('x', makePrimitiveType(Kind.Int16), false),
new Field('s', makePrimitiveType(Kind.String), false),
new Field('b', makePrimitiveType(Kind.Bool), false)
], []);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Value, Kind.Unresolved, pkg.ref.toString(), 0, 42, 'hi', true];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assertStruct(v, tr.desc, {
x: 42,
s: 'hi',
b: true
});
});
test('test read enum', async () => {
let ms = new MemoryStore();
let tr = makeEnumType('E', ['a', 'b', 'c']);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Unresolved, pkg.ref.toString(), 0, 1];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assert.deepEqual(1, v);
});
test('test read value enum', async () => {
let ms = new MemoryStore();
let tr = makeEnumType('E', ['a', 'b', 'c']);
let pkg = new Package([tr], []);
registerPackage(pkg);
let a = [Kind.Value, Kind.Unresolved, pkg.ref.toString(), 0, 1];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assert.deepEqual(1, v);
});
test('test read struct with', async () => {
let ms = new MemoryStore();
let tr = makeStructType('A1', [
new Field('x', makePrimitiveType(Kind.Int16), false),
new Field('e', makeType(new Ref(), 1), false),
new Field('b', makePrimitiveType(Kind.Bool), false)
], []);
let enumTref = makeEnumType('E', ['a', 'b', 'c']);
let pkg = new Package([tr, enumTref], []);
registerPackage(pkg);
let a = [Kind.Unresolved, pkg.ref.toString(), 0, 42, 1, true];
let r = new JsonArrayReader(a, ms);
let v = await r.readTopLevelValue();
assertStruct(v, tr.desc, {
x: 42,
e: 1,
b: true
});
});
test('test read map of string to struct', async () => {
let ms = new MemoryStore();
let tr = makeStructType('s', [
+17 -3
View File
@@ -9,7 +9,7 @@ import {encode as encodeBase64} from './base64.js';
import {invariant, notNull} from './assert.js';
import {isPrimitiveKind, Kind} from './noms_kind.js';
import {lookupPackage, Package} from './package.js';
import {makePrimitiveType, StructDesc, Type} from './type.js';
import {makePrimitiveType, EnumDesc, StructDesc, Type} from './type.js';
const typedTag = 't ';
@@ -166,7 +166,15 @@ class JsonArrayWriter {
this.writeKind(k);
switch (k) {
case Kind.Enum:
throw new Error('Not implemented');
let desc = t.desc;
invariant(desc instanceof EnumDesc);
this.write(t.name);
let w2 = new JsonArrayWriter(this._cs);
for (let i = 0; i < desc.ids.length; i++) {
w2.write(desc.ids[i]);
}
this.write(w2.array);
break;
case Kind.List:
case Kind.Map:
case Kind.Ref:
@@ -224,7 +232,9 @@ class JsonArrayWriter {
let typeDef = pkg.types[t.ordinal];
switch (typeDef.kind) {
case Kind.Enum:
throw new Error('Not implemented');
invariant(typeof v === 'number');
this.writeEnum(v);
break;
case Kind.Struct: {
invariant(v instanceof Struct);
this.writeStruct(v, t, typeDef, pkg);
@@ -263,6 +273,10 @@ class JsonArrayWriter {
this.writeValue(s.get(unionField.name), unionField.t, pkg);
}
}
writeEnum(v: number) {
this.writeNumber(v);
}
}
function orderValuesByRef(t: Type, a: Array<any>): Array<any> {
+62 -1
View File
@@ -7,7 +7,7 @@ import MemoryStore from './memory_store.js';
import Ref from './ref.js';
import Struct from './struct.js';
import test from './async_test.js';
import {Field, makeCompoundType, makePrimitiveType, makeStructType, makeType} from './type.js';
import {Field, makeCompoundType, makeEnumType, makePrimitiveType, makeStructType, makeType, Type} from './type.js';
import {JsonArrayWriter, encodeNomsValue} from './encode.js';
import {Kind} from './noms_kind.js';
import {Package, registerPackage} from './package.js';
@@ -239,6 +239,67 @@ suite('Encode', () => {
assert.deepEqual([Kind.Unresolved, pkgRef.toString(), 1, 42], w.array);
});
test('write enum', async () => {
let ms = new MemoryStore();
let w = new JsonArrayWriter(ms);
let pkg = new Package([makeEnumType('E', ['a', 'b', 'c'])], []);
registerPackage(pkg);
let pkgRef = pkg.ref;
let typ = makeType(pkgRef, 0);
w.writeTopLevel(typ, 1);
assert.deepEqual([Kind.Unresolved, pkgRef.toString(), 0, 1], w.array);
});
test('write list of enum', async () => {
let ms = new MemoryStore();
let w = new JsonArrayWriter(ms);
let pkg = new Package([makeEnumType('E', ['a', 'b', 'c'])], []);
registerPackage(pkg);
let pkgRef = pkg.ref;
let typ = makeType(pkgRef, 0);
let listType = makeCompoundType(Kind.List, typ);
let l = [0, 1, 2];
w.writeTopLevel(listType, l);
assert.deepEqual([Kind.List, Kind.Unresolved, pkgRef.toString(), 0, [0, 1, 2]], w.array);
});
test('write type value', async () => {
let ms = new MemoryStore();
let test = (expected: Array<any>, v: Type) => {
let w = new JsonArrayWriter(ms);
w.writeTopLevel(v.type, v);
assert.deepEqual(expected, w.array);
};
test([Kind.Type, Kind.Int32], makePrimitiveType(Kind.Int32));
test([Kind.Type, Kind.List, [Kind.Bool]], makeCompoundType(Kind.List, makePrimitiveType(Kind.Bool)));
test([Kind.Type, Kind.Map, [Kind.Bool, Kind.String]], makeCompoundType(Kind.Map, makePrimitiveType(Kind.Bool), makePrimitiveType(Kind.String)));
test([Kind.Type, Kind.Enum, 'E', ['a', 'b', 'c']], makeEnumType('E', ['a', 'b', 'c']));
test([Kind.Type, Kind.Struct, 'S', ['x', Kind.Int16, false, 'v', Kind.Value, true], []], makeStructType('S', [
new Field('x', makePrimitiveType(Kind.Int16), false),
new Field('v', makePrimitiveType(Kind.Value), true)
], []));
test([Kind.Type, Kind.Struct, 'S', [], ['x', Kind.Int16, false, 'v', Kind.Value, false]], makeStructType('S', [], [
new Field('x', makePrimitiveType(Kind.Int16), false),
new Field('v', makePrimitiveType(Kind.Value), false)
]));
let pkgRef = Ref.parse('sha1-0123456789abcdef0123456789abcdef01234567');
test([Kind.Type, Kind.Unresolved, pkgRef.toString(), 123], makeType(pkgRef, 123));
test([Kind.Type, Kind.Struct, 'S', ['e', Kind.Unresolved, pkgRef.toString(), 123, false, 'x', Kind.Int64, false], []], makeStructType('S', [
new Field('e', makeType(pkgRef, 123), false),
new Field('x', makePrimitiveType(Kind.Int64), false)
], []));
// test([Kind.Type, Kind.Unresolved, new Ref().toString(), -1, 'ns', 'n'], makeUnresolvedType('ns', 'n'));
});
test('top level blob', () => {
function stringToBuffer(s) {
let bytes = new Uint8Array(s.length);
+62 -20
View File
@@ -37,8 +37,12 @@ class UnresolvedDesc {
}
equals(other: TypeDesc): boolean {
return other instanceof UnresolvedDesc && other._pkgRef.equals(this._pkgRef)
&& other._ordinal === this._ordinal;
if (other.kind !== this.kind) {
return false;
}
invariant(other instanceof UnresolvedDesc);
return other._pkgRef.equals(this._pkgRef) && other._ordinal === this._ordinal;
}
}
@@ -71,6 +75,37 @@ class CompoundDesc {
}
}
class EnumDesc {
ids: Array<string>;
constructor(ids: Array<string>) {
this.ids = ids;
}
get kind(): NomsKind {
return Kind.Enum;
}
equals(other: TypeDesc): boolean {
if (other.kind !== this.kind) {
return false;
}
invariant(other instanceof EnumDesc);
if (other.ids.length !== this.ids.length) {
return false;
}
for (let i = 0; i < this.ids.length; i++) {
if (this.ids[i] !== other.id[i]) {
return false;
}
}
return true;
}
}
class StructDesc {
fields: Array<Field>;
union: Array<Field>;
@@ -85,27 +120,28 @@ class StructDesc {
}
equals(other: TypeDesc): boolean {
if (other instanceof StructDesc) {
if (this.fields.length !== other.fields.length || this.union.length !== other.union.length) {
return false;
}
if (other.kind !== this.kind) {
return false;
}
invariant(other instanceof StructDesc);
for (let i = 0; i < this.fields.length; i++) {
if (!this.fields[i].equals(other.fields[i])) {
return false;
}
}
for (let i = 0; i < this.union.length; i++) {
if (!this.union[i].equals(other.union[i])) {
return false;
}
}
return true;
if (this.fields.length !== other.fields.length || this.union.length !== other.union.length) {
return false;
}
return false;
for (let i = 0; i < this.fields.length; i++) {
if (!this.fields[i].equals(other.fields[i])) {
return false;
}
}
for (let i = 0; i < this.union.length; i++) {
if (!this.union[i].equals(other.union[i])) {
return false;
}
}
return true;
}
}
@@ -237,6 +273,10 @@ function makeCompoundType(k: NomsKind, ...elemTypes: Array<Type>): Type {
return buildType('', new CompoundDesc(k, elemTypes));
}
function makeEnumType(name: string, ids: Array<string>): Type {
return buildType(name, new EnumDesc(ids));
}
function makeStructType(name: string, fields: Array<Field>, choices: Array<Field>): Type {
return buildType(name, new StructDesc(fields, choices));
}
@@ -254,8 +294,10 @@ let packageType = makePrimitiveType(Kind.Package);
export {
CompoundDesc,
EnumDesc,
Field,
makeCompoundType,
makeEnumType,
makePrimitiveType,
makeStructType,
makeType,