(js2) Add HttpStore & more decode/encode support

This commit is contained in:
Rafael Weinstein
2015-11-02 11:23:49 -08:00
parent 02dda2e161
commit 9017dced4f
10 changed files with 354 additions and 91 deletions

2
js2/link.sh Executable file
View File

@@ -0,0 +1,2 @@
# nothing to link
npm link

View File

@@ -4,7 +4,8 @@
"dependencies": {
"rusha": "^0.8.3",
"flow-bin": "^0.18.1",
"text-encoding": "^0.5.2"
"text-encoding": "^0.5.2",
"isomorphic-fetch": "^2.2.0"
},
"devDependencies": {
"babel": "^5.6.23",

View File

@@ -11,15 +11,14 @@ const chunkHeaderSize = sha1Size + chunkLengthSize;
export function serialize(chunks: Array<Chunk>): ArrayBuffer {
let totalSize = 0;
for (let i = 0; i < chunks.length; i++) {
totalSize += chunkHeaderSize + chunks[i].data.length;
for (let chunk of chunks) {
totalSize += chunkHeaderSize + chunk.data.length;
}
let buffer = new ArrayBuffer(totalSize);
let offset = 0;
for (let i = 0; i < chunks.length; i++) {
let chunk = chunks[i];
for (let chunk of chunks) {
let refArray = new Uint8Array(buffer, offset, sha1Size);
refArray.set(chunk.ref.digest);
offset += sha1Size;

View File

@@ -3,13 +3,12 @@
'use strict';
import Chunk from './chunk.js';
import MemoryStore from './memory_store.js';
import Ref from './ref.js';
import type {ChunkStore} from './chunk_store.js';
import type {NomsKind} from './noms_kind.js';
import {isPrimitiveKind, Kind} from './noms_kind.js';
import {lookupPackage, Package} from './package.js';
import {makeCompoundTypeRef, makePrimitiveTypeRef, makeTypeRef, StructDesc, TypeRef} from './type_ref.js';
import {lookupPackage, Package, readPackage} from './package.js';
import {Field, makeCompoundTypeRef, makePrimitiveTypeRef, makeStructTypeRef, makeTypeRef, makeUnresolvedTypeRef, StructDesc, TypeRef} from './type_ref.js';
const typedTag = 't ';
@@ -113,46 +112,62 @@ class JsonArrayReader {
throw new Error('Unreachable');
}
readList(t: TypeRef, pkg: ?Package): Array<any> {
async readList(t: TypeRef, pkg: ?Package): Promise<Array<any>> {
let elemType = t.elemTypes[0];
let list = [];
while (!this.atEnd()) {
let v = this.readValueWithoutTag(elemType, pkg);
list.push(v);
}
return list;
return Promise.all(list);
}
readSet(t: TypeRef, pkg: ?Package): Set {
let elemType = t.elemTypes[0];
let s = new Set();
while (!this.atEnd()) {
let v = this.readValueWithoutTag(elemType, pkg);
s.add(v);
}
return s;
async readSet(t: TypeRef, pkg: ?Package): Promise<Set> {
let seq = await this.readList(t, pkg);
return new Set(seq);
}
readMap(t: TypeRef, pkg: ?Package): Map {
async readMap(t: TypeRef, pkg: ?Package): Promise<Map> {
let keyType = t.elemTypes[0];
let valueType = t.elemTypes[1];
let m = new Map();
let kv = [];
while (!this.atEnd()) {
let k = this.readValueWithoutTag(keyType, pkg);
let v = this.readValueWithoutTag(valueType, pkg);
m.set(k, v);
kv.push(this.readValueWithoutTag(keyType, pkg));
kv.push(this.readValueWithoutTag(valueType, pkg));
}
kv = await Promise.all(kv);
let m = new Map();
for (let i = 0; i < kv.length; i += 2) {
m.set(kv[i], kv[i + 1]);
}
return m;
}
readTopLevelValue(): any {
readPackage(t: TypeRef, pkg: ?Package): Package {
let r2 = new JsonArrayReader(this.readArray(), this._cs);
let types = [];
while (!r2.atEnd()) {
types.push(r2.readTypeRefAsValue(pkg));
}
let r3 = new JsonArrayReader(this.readArray(), this._cs);
let deps = [];
while (!r3.atEnd()) {
deps.push(r3.readRef());
}
return new Package(types, deps);
}
async readTopLevelValue(): Promise<any> {
let t = this.readTypeRefAsTag();
return this.readValueWithoutTag(t);
}
readValueWithoutTag(t: TypeRef, pkg: ?Package = null): any {
async readValueWithoutTag(t: TypeRef, pkg: ?Package = null): Promise<any> {
// TODO: Verify read values match tagged kinds.
switch (t.kind) {
case Kind.Blob:
@@ -185,9 +200,9 @@ class JsonArrayReader {
return r2.readMap(t, pkg);
}
case Kind.Package:
throw new Error('Not implemented');
return this.readPackage(t, pkg);
case Kind.Ref:
throw new Error('Not implemented');
return this.readRef();
case Kind.Set: {
let r2 = new JsonArrayReader(this.readArray(), this._cs);
return r2.readSet(t, pkg);
@@ -196,6 +211,7 @@ class JsonArrayReader {
case Kind.Struct:
throw new Error('Not allowed');
case Kind.TypeRef:
return this.readTypeRefAsValue(pkg);
case Kind.Unresolved:
return this.readUnresolvedKindToValue(t, pkg);
}
@@ -203,13 +219,13 @@ class JsonArrayReader {
throw new Error('Unreached');
}
readUnresolvedKindToValue(t: TypeRef, pkg: ?Package = null): any {
async readUnresolvedKindToValue(t: TypeRef, pkg: ?Package = null): Promise<any> {
let pkgRef = t.packageRef;
let ordinal = t.ordinal;
if (!pkgRef.isEmpty()) {
let pkg2 = lookupPackage(pkgRef);
if (!pkg2) {
throw new Error('Not implemented');
pkg = await readPackage(pkgRef, this._cs);
} else {
pkg = pkg2;
}
@@ -231,23 +247,83 @@ class JsonArrayReader {
}
}
readStruct(typeDef: TypeRef, typeRef: TypeRef, pkg: Package): any {
readTypeRefAsValue(pkg: ?Package): TypeRef {
let k = this.readKind();
switch (k) {
case Kind.Enum:
throw new Error('Not implemented');
case Kind.List:
case Kind.Map:
case Kind.Ref:
case Kind.Set: {
let r2 = new JsonArrayReader(this.readArray(), this._cs);
let elemTypes: Array<TypeRef> = [];
while (!r2.atEnd()) {
elemTypes.push(r2.readTypeRefAsValue());
}
return makeCompoundTypeRef(k, ...elemTypes);
}
case Kind.Struct: {
let name = this.readString();
let readFields = () => {
let fields: Array<Field> = [];
let fieldReader = new JsonArrayReader(this.readArray(), this._cs);
while (!fieldReader.atEnd()) {
let fieldName = fieldReader.readString();
let fieldType = fieldReader.readTypeRefAsValue(pkg);
let optional = fieldReader.readBool();
fields.push(new Field(fieldName, fieldType, optional));
}
return fields;
};
let fields = readFields();
let choices = readFields();
return makeStructTypeRef(name, fields, choices);
}
case Kind.Unresolved: {
let pkgRef = this.readRef();
let ordinal = this.readOrdinal();
if (ordinal === -1) {
let namespace = this.readString();
let name = this.readString();
if (!pkgRef.isEmpty()) {
throw new Error('Unresolved TypeRefs may not have a package ref');
}
return makeUnresolvedTypeRef(namespace, name);
}
return makeTypeRef(pkgRef, ordinal);
}
default: {
if (!isPrimitiveKind(k)) {
throw new Error('Not implemented: ' + k);
}
return makePrimitiveTypeRef(k);
}
}
}
async readStruct(typeDef: TypeRef, typeRef: TypeRef, pkg: Package): Promise<any> {
// TODO FixupTypeRef?
// TODO Make read of sub-values parallel.
let desc = typeDef.desc;
if (desc instanceof StructDesc) {
let s = Object.create(null);
for (let i = 0; i < desc.fields.length; i++) {
let field = desc.fields[i];
let s: { [key: string]: any } = Object.create(null);
s._typeRef = typeDef; // TODO: Need a better way to add typeRef
for (let field of desc.fields) {
if (field.optional) {
let b = this.readBool();
if (b) {
let v = this.readValueWithoutTag(field.t, pkg);
let v = await this.readValueWithoutTag(field.t, pkg);
s[field.name] = v;
}
} else {
let v = this.readValueWithoutTag(field.t, pkg);
let v = await this.readValueWithoutTag(field.t, pkg);
s[field.name] = v;
}
}
@@ -263,14 +339,13 @@ class JsonArrayReader {
}
}
function decodeNomsValue(chunk: Chunk): any {
function decodeNomsValue(chunk: Chunk, cs: ChunkStore): Promise<any> {
let tag = new Chunk(new Uint8Array(chunk.data.buffer, 0, 2)).toString();
switch (tag) {
case typedTag: {
let ms = new MemoryStore(); // This needs to be handed in.
let payload = JSON.parse(new Chunk(new Uint8Array(chunk.data.buffer, 2)).toString());
let reader = new JsonArrayReader(payload, ms);
let reader = new JsonArrayReader(payload, cs);
return reader.readTopLevelValue();
}
default:
@@ -278,4 +353,13 @@ function decodeNomsValue(chunk: Chunk): any {
}
}
export {decodeNomsValue, JsonArrayReader};
export async function readValue(r: Ref, cs: ChunkStore): Promise<any> {
let chunk = await cs.get(r);
if (chunk.isEmpty()) {
return null;
}
return decodeNomsValue(chunk, cs);
}
export {decodeNomsValue, JsonArrayReader, readValue};

View File

@@ -7,7 +7,7 @@ import MemoryStore from './memory_store.js';
import Ref from './ref.js';
import test from './async_test.js';
import {assert} from 'chai';
import {decodeNomsValue, JsonArrayReader} from './decode.js';
import {decodeNomsValue, JsonArrayReader, readValue} from './decode.js';
import {Field, makeCompoundTypeRef, makePrimitiveTypeRef, makeStructTypeRef, makeTypeRef, TypeRef} from './type_ref.js';
import {Kind} from './noms_kind.js';
import {registerPackage, Package} from './package.js';
@@ -51,9 +51,9 @@ suite('Decode', () => {
test('read primitives', async () => {
let ms = new MemoryStore();
function doTest(expected: any, a: Array<any>) {
async function doTest(expected: any, a: Array<any>): Promise<void> {
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
assert.strictEqual(expected, v);
}
@@ -79,7 +79,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.List, Kind.Int32, [0, 1, 2, 3]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
assert.deepEqual([0, 1, 2, 3], v);
});
@@ -87,7 +87,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.List, Kind.Value, [Kind.Int32, 1, Kind.String, 'hi', Kind.Bool, true]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
assert.deepEqual([1, 'hi', true], v);
});
@@ -95,7 +95,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.Value, Kind.List, Kind.Int8, [0, 1, 2]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
assert.deepEqual([0, 1, 2], v);
});
@@ -111,7 +111,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.Map, Kind.Int64, Kind.Float64, [0, 1, 2, 3]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
let m = new Map();
m.set(0, 1);
@@ -124,7 +124,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.Value, Kind.Map, Kind.UInt64, Kind.UInt32, [0, 1, 2, 3]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
let m = new Map();
m.set(0, 1);
@@ -144,7 +144,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.Set, Kind.UInt8, [0, 1, 2, 3]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
let s = new Set();
s.add(0);
@@ -159,7 +159,7 @@ suite('Decode', () => {
let ms = new MemoryStore();
let a = [Kind.Value, Kind.Set, Kind.UInt16, [0, 1, 2, 3]];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
let v = await r.readTopLevelValue();
let s = new Set([0, 1, 2, 3]);
assertSetsEqual(s, v);
@@ -178,14 +178,27 @@ suite('Decode', () => {
let a = [Kind.Unresolved, pkg.ref.toString(), 0, 42, 'hi', true];
let r = new JsonArrayReader(a, ms);
let v = r.readTopLevelValue();
assert.deepEqual({x: 42, s: 'hi', b: true}, v);
let v = await r.readTopLevelValue();
assert.deepEqual({x: 42, s: 'hi', b: true, _typeRef: tr}, v);
});
test('decodeNomsValue', async () => {
let chunk = Chunk.fromString(`t [${Kind.Value}, ${Kind.Set}, ${Kind.UInt16}, [0, 1, 2, 3]]`);
let v = decodeNomsValue(chunk);
let v = await decodeNomsValue(chunk, new MemoryStore());
let s = new Set([0, 1, 2, 3]);
assertSetsEqual(s, v);
});
test('decodeNomsValue: counter with one commit', async () => {
let ms = new MemoryStore();
let root = Ref.parse('sha1-a53578b3f9f39646df642f010fc9924aec0b4b2f');
ms.put(Chunk.fromString('t [15,11,16,21,"sha1-7546d804d845125bc42669c7a4c3f3fb909eca29",0,["counter","sha1-d796f8295b4ffa0a0711bfb844f07827012923d3"]]')); // root
ms.put(Chunk.fromString('t [22,[19,"Commit",["value",13,false,"parents",17,[16,[21,"sha1-0000000000000000000000000000000000000000",0]],false],[]],[]]')); // datas package
ms.put(Chunk.fromString('t [21,"sha1-7546d804d845125bc42669c7a4c3f3fb909eca29",0,4,1,[]]')); // commit
let rootMap = await readValue(root, ms);
let counterRef = rootMap.get('counter');
let commit = await readValue(counterRef, ms);
assert.strictEqual(commit.value, 1);
});
});

View File

@@ -9,7 +9,7 @@ import type {ChunkStore} from './chunk_store.js';
import type {NomsKind} from './noms_kind.js';
import {isPrimitiveKind, Kind} from './noms_kind.js';
import {makePrimitiveTypeRef, StructDesc, TypeRef} from './type_ref.js';
import {Package} from './package.js';
import {lookupPackage, Package} from './package.js';
const typedTag = 't ';
@@ -45,10 +45,7 @@ class JsonArrayWriter {
case Kind.Map:
case Kind.Ref:
case Kind.Set: {
let elemTypes = t.elemTypes;
for (let i = 0; i < elemTypes.length; i++) {
this.writeTypeRefAsTag(elemTypes[i]);
}
t.elemTypes.forEach(elemType => this.writeTypeRefAsTag(elemType));
break;
}
case Kind.Unresolved:
@@ -83,9 +80,7 @@ class JsonArrayWriter {
if (v instanceof Array) {
let w2 = new JsonArrayWriter(this._cs);
let elemType = t.elemTypes[0];
for (let i = 0; i < v.length; i++) {
w2.writeValue(v[i], elemType);
}
v.forEach(sv => w2.writeValue(sv, elemType));
this.write(w2.array);
} else {
throw new Error('Attempt to serialize non-list as list');
@@ -103,10 +98,10 @@ class JsonArrayWriter {
elems.push(k);
});
elems = orderValuesByRef(keyType, elems);
for (let i = 0; i < elems.length; i++) {
w2.writeValue(elems[i], keyType);
w2.writeValue(v.get(elems[i]), valueType);
}
elems.forEach(elem => {
w2.writeValue(elem, keyType);
w2.writeValue(v.get(elem), valueType);
});
this.write(w2.array);
} else {
throw new Error('Attempt to serialize non-map as maps');
@@ -118,14 +113,10 @@ class JsonArrayWriter {
if (v instanceof Package) {
let ptr = makePrimitiveTypeRef(Kind.TypeRef);
let w2 = new JsonArrayWriter(this._cs);
for (let i = 0; i < v.types.length; i++) {
w2.writeValue(v.types[i], ptr);
}
v.types.forEach(type => w2.writeValue(type, ptr));
this.write(w2.array);
let w3 = new JsonArrayWriter(this._cs);
for (let i = 0; i < v.dependencies.length; i++) {
w3.writeRef(v.dependencies[i]);
}
v.dependencies.forEach(ref => w3.writeRef(ref));
this.write(w3.array);
} else {
throw new Error('Attempt to serialize non-package as package');
@@ -142,9 +133,7 @@ class JsonArrayWriter {
elems.push(v);
});
elems = orderValuesByRef(elemType, elems);
for (let i = 0; i < elems.length; i++) {
w2.writeValue(elems[i], elemType);
}
elems.forEach(elem => w2.writeValue(elem, elemType));
this.write(w2.array);
} else {
throw new Error('Attempt to serialize non-set as set');
@@ -176,9 +165,7 @@ class JsonArrayWriter {
case Kind.Set: {
this.write(t.name);
let w2 = new JsonArrayWriter(this._cs);
for (let i = 0; t.elemTypes.length; i++) {
w2.writeTypeRefAsValue(t.elemTypes[i]);
}
t.elemTypes.forEach(elem => w2.writeTypeRefAsValue(elem));
this.write(w2.array);
break;
}
@@ -187,20 +174,18 @@ class JsonArrayWriter {
if (desc instanceof StructDesc) {
this.write(t.name);
let fieldWriter = new JsonArrayWriter(this._cs);
for (let i = 0; i < desc.fields.length; i++) {
let field = desc.fields[i];
desc.fields.forEach(field => {
fieldWriter.write(field.name);
fieldWriter.writeTypeRefAsValue(field.t);
fieldWriter.write(field.optional);
}
});
this.write(fieldWriter.array);
let choiceWriter = new JsonArrayWriter(this._cs);
for (let i = 0; i < desc.union.length; i++) {
let choice = desc.union[i];
desc.union.forEach(choice => {
choiceWriter.write(choice.name);
choiceWriter.writeTypeRefAsValue(choice.t);
choiceWriter.write(choice.optional);
}
});
this.write(choiceWriter.array);
} else {
throw new Error('Attempt to serialize non-struct typeref as struct type-ref');
@@ -208,8 +193,23 @@ class JsonArrayWriter {
break;
}
case Kind.Unresolved:
throw new Error('Not implemented');
case Kind.Unresolved: {
let pkgRef = t.packageRef;
this.writeRef(pkgRef);
let ordinal = t.ordinal;
this.write(ordinal);
if (ordinal === -1) {
this.write(t.namespace);
this.write(t.name);
}
let pkg = lookupPackage(pkgRef);
if (pkg) {
throw new Error('Not implemented');
}
break;
}
default: {
if (!isPrimitiveKind(k)) {
throw new Error('Not implemented.');

136
js2/src/http_store.js Normal file
View File

@@ -0,0 +1,136 @@
/* @flow */
'use strict';
import Chunk from './chunk.js';
import fetch from 'isomorphic-fetch';
import Ref from './ref.js';
import {deserialize} from './chunk_serializer.js';
type ReadRequest = {
resolve: (c: Chunk) => void,
reject: (e: Error) => void
};
function blobToBuffer(blob: Blob): Promise<ArrayBuffer> {
return new Promise((resolve) => {
let reader = new FileReader();
reader.addEventListener('loadend', () => {
resolve(reader.result);
});
reader.readAsArrayBuffer(blob);
});
}
export default class HttpStore {
_rpc: {
getRefs: string,
ref: string,
root: string
};
_readQueue: { [key: string]: Array<ReadRequest> };
_anyPending: boolean;
_fetchScheduled: boolean;
_activeReads: number;
_maxReads: number;
constructor(url: string, maxReads: number = 3) {
this._rpc = {
getRefs: url + '/getRefs/',
ref: url + '/ref',
root: url + '/root'
};
this._readQueue = Object.create(null);
this._anyPending = false;
this._fetchScheduled = false;
this._activeReads = 0;
this._maxReads = maxReads;
}
async getRoot(): Promise<Ref> {
let r = await fetch(this._rpc.root);
let refStr = await r.text();
return Ref.parse(refStr);
}
async get(ref: Ref): Promise<Chunk> {
return new Promise((resolve, reject) => {
let refStr = ref.toString();
if (!this._readQueue[refStr]) {
this._readQueue[refStr] = [];
}
this._readQueue[refStr].push({resolve, reject});
this._anyPending = true;
this._pumpFetchQueue();
});
}
_pumpFetchQueue() {
if (!this._fetchScheduled && this._anyPending && this._activeReads < this._maxReads) {
this._fetchScheduled = true;
setTimeout(() => {
this._beginFetch();
}, 0);
}
}
async _beginFetch(): Promise<void> {
this._activeReads++;
let reqs = this._readQueue;
this._readQueue = Object.create(null);
this._anyPending = false;
this._fetchScheduled = false;
let refStrs = Object.keys(reqs);
let body = refStrs.map(r => 'ref=' + r).join('&');
try {
let response = await fetch(this._rpc.getRefs, {
method: 'post',
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
if (response.status !== 200) {
throw new Error('Buffered read failed: ' + response.status);
}
let blob = await response.blob();
let buffer = await blobToBuffer(blob);
let chunks = deserialize(buffer);
// Return success
chunks.forEach(chunk => {
let refStr = chunk.ref.toString();
let callers = reqs[refStr];
delete reqs[refStr];
callers.forEach(caller => {
caller.resolve(chunk);
});
});
// Report failure
Object.keys(reqs).forEach(r => {
let callers = reqs[r];
callers.forEach(c => {
c.reject(new Chunk());
});
});
} catch (err) {
// TODO: This is fatal.
throw err;
} finally {
this._endFetch();
}
}
_endFetch() {
this._activeReads--;
this._pumpFetchQueue();
}
close() {}
}

View File

@@ -3,16 +3,18 @@
'use strict';
import Chunk from './chunk.js';
import HttpStore from './http_store.js';
import MemoryStore from './memory_store.js';
import Ref from './ref.js';
import {decodeNomsValue} from './decode.js';
import {readValue} from './decode.js';
import {encodeNomsValue} from './encode.js';
import {TypeRef} from './type_ref.js';
export {
Chunk,
decodeNomsValue,
readValue,
encodeNomsValue,
HttpStore,
MemoryStore,
Ref,
TypeRef

View File

@@ -2,10 +2,12 @@
'use strict';
import {readValue} from './decode.js';
import Ref from './ref.js';
import type {ChunkStore} from './chunk_store.js';
import {encodeNomsValue} from './encode.js';
import {Kind} from './noms_kind.js';
import {makePrimitiveTypeRef, TypeRef} from './type_ref.js';
import {encodeNomsValue} from './encode.js';
const packageTypeRef = makePrimitiveTypeRef(Kind.Package);
@@ -42,4 +44,14 @@ function registerPackage(p: Package) {
packageRegistry[p.ref.toString()] = p;
}
export {lookupPackage, Package, registerPackage};
async function readPackage(r: Ref, cs: ChunkStore): Promise<Package> {
let p = await readValue(r, cs);
if (p instanceof Package) {
registerPackage(p);
return p;
} else {
throw new Error('Non-package found where package expected.');
}
}
export {lookupPackage, Package, readPackage, registerPackage};

View File

@@ -255,4 +255,18 @@ function makeTypeRef(pkgRef: Ref, ordinal: number): TypeRef {
return new TypeRef('', '', new UnresolvedDesc(pkgRef, ordinal));
}
export {CompoundDesc, Field, makeCompoundTypeRef, makePrimitiveTypeRef, makeStructTypeRef, makeTypeRef, StructDesc, TypeRef};
function makeUnresolvedTypeRef(namespace: string, name: string): TypeRef {
return new TypeRef(name, namespace, new UnresolvedDesc(new Ref(), -1));
}
export {
CompoundDesc,
Field,
makeCompoundTypeRef,
makePrimitiveTypeRef,
makeStructTypeRef,
makeTypeRef,
makeUnresolvedTypeRef,
StructDesc,
TypeRef
};