Files
dolt/js/src/value-decoder.js
Rafael Weinstein 8a5f3853b7 Revert "Js type cache (#2011)"
This reverts commit 4e10ae63f4.
2016-07-11 18:36:17 -07:00

232 lines
6.6 KiB
JavaScript

// @flow
// Copyright 2016 Attic Labs, Inc. All rights reserved.
// Licensed under the Apache License, version 2.0:
// http://www.apache.org/licenses/LICENSE-2.0
import Blob, {BlobLeafSequence} from './blob.js';
import Ref, {constructRef} from './ref.js';
import {newStructWithType} from './struct.js';
import type Struct from './struct.js';
import type {NomsKind} from './noms-kind.js';
import {
getPrimitiveType,
makeListType,
makeMapType,
makeRefType,
makeSetType,
makeUnionType,
StructDesc,
Type,
} from './type.js';
import {OrderedKey, MetaTuple} from './meta-sequence.js';
import {invariant} from './assert.js';
import {isPrimitiveKind, kindToString, Kind} from './noms-kind.js';
import List, {ListLeafSequence} from './list.js';
import Map, {MapLeafSequence} from './map.js';
import Set, {SetLeafSequence} from './set.js';
import {IndexedMetaSequence, OrderedMetaSequence} from './meta-sequence.js';
import type Value from './value.js';
import type {ValueReader} from './value-store.js';
import type {NomsReader} from './codec.js';
export default class ValueDecoder {
_r: NomsReader;
_ds: ValueReader;
constructor(r: NomsReader, ds: ValueReader) {
this._r = r;
this._ds = ds;
}
readKind(): NomsKind {
return this._r.readUint8();
}
readRef(t: Type): Ref {
const hash = this._r.readHash();
const height = this._r.readUint64();
return constructRef(t, hash, height);
}
readType(parentStructTypes: Type[]): Type {
const k = this.readKind();
switch (k) {
case Kind.List:
return makeListType(this.readType(parentStructTypes));
case Kind.Map:
return makeMapType(this.readType(parentStructTypes),
this.readType(parentStructTypes));
case Kind.Set:
return makeSetType(this.readType(parentStructTypes));
case Kind.Ref:
return makeRefType(this.readType(parentStructTypes));
case Kind.Struct:
return this.readStructType(parentStructTypes);
case Kind.Union: {
const len = this._r.readUint32();
const types: Type[] = new Array(len);
for (let i = 0; i < len; i++) {
types[i] = this.readType(parentStructTypes);
}
return makeUnionType(types);
}
case Kind.Cycle: {
const i = this._r.readUint32();
return parentStructTypes[parentStructTypes.length - 1 - i];
}
}
invariant(isPrimitiveKind(k));
return getPrimitiveType(k);
}
readBlobLeafSequence(): BlobLeafSequence {
const bytes = this._r.readBytes();
return new BlobLeafSequence(this._ds, bytes);
}
readValueSequence(): Array<Value> {
const count = this._r.readUint32();
const list = [];
for (let i = 0; i < count; i++) {
const v = this.readValue();
list.push(v);
}
return list;
}
readListLeafSequence(t: Type): ListLeafSequence {
const data = this.readValueSequence();
return new ListLeafSequence(this._ds, t, data);
}
readSetLeafSequence(t: Type): SetLeafSequence {
const data = this.readValueSequence();
return new SetLeafSequence(this._ds, t, data);
}
readMapLeafSequence(t: Type): MapLeafSequence {
const count = this._r.readUint32();
const data = [];
for (let i = 0; i < count; i++) {
const k = this.readValue();
const v = this.readValue();
data.push([k, v]);
}
return new MapLeafSequence(this._ds, t, data);
}
readMetaSequence(): Array<MetaTuple> {
const count = this._r.readUint32();
const data: Array<MetaTuple> = [];
for (let i = 0; i < count; i++) {
const ref = this.readValue();
const v = this.readValue();
const key = v instanceof Ref ? OrderedKey.fromHash(v.targetHash) : new OrderedKey(v);
const numLeaves = this._r.readUint64();
data.push(new MetaTuple(ref, key, numLeaves, null));
}
return data;
}
readIndexedMetaSequence(t: Type): IndexedMetaSequence {
return new IndexedMetaSequence(this._ds, t, this.readMetaSequence());
}
readOrderedMetaSequence(t: Type): OrderedMetaSequence {
return new OrderedMetaSequence(this._ds, t, this.readMetaSequence());
}
readValue(): any {
const t = this.readType([]);
switch (t.kind) {
case Kind.Blob: {
const isMeta = this._r.readBool();
if (isMeta) {
return Blob.fromSequence(this.readIndexedMetaSequence(t));
}
return Blob.fromSequence(this.readBlobLeafSequence());
}
case Kind.Bool:
return this._r.readBool();
case Kind.Number:
return this._r.readNumber();
case Kind.String:
return this._r.readString();
case Kind.List: {
const isMeta = this._r.readBool();
if (isMeta) {
return List.fromSequence(this.readIndexedMetaSequence(t));
}
return List.fromSequence(this.readListLeafSequence(t));
}
case Kind.Map: {
const isMeta = this._r.readBool();
if (isMeta) {
return Map.fromSequence(this.readOrderedMetaSequence(t));
}
return Map.fromSequence(this.readMapLeafSequence(t));
}
case Kind.Ref:
return this.readRef(t);
case Kind.Set: {
const isMeta = this._r.readBool();
if (isMeta) {
return Set.fromSequence(this.readOrderedMetaSequence(t));
}
return Set.fromSequence(this.readSetLeafSequence(t));
}
case Kind.Struct:
return this.readStruct(t);
case Kind.Type:
return this.readType([]);
case Kind.Cycle:
case Kind.Union:
case Kind.Value:
throw new Error('A value instance can never have type' + kindToString[t.kind]);
}
throw new Error('Unreached');
}
readStruct<T: Struct>(type: Type): T {
const {desc} = type;
invariant(desc instanceof StructDesc);
const count = desc.fieldCount;
const values = new Array(count);
for (let i = 0; i < count; i++) {
values[i] = this.readValue();
}
return newStructWithType(type, values);
}
readStructType(parentStructTypes: Type[]): Type {
const name = this._r.readString();
const count = this._r.readUint32();
const fields = new Array(count);
const desc = new StructDesc(name, fields);
const structType = new Type(desc);
parentStructTypes.push(structType);
for (let i = 0; i < count; i++) {
const name = this._r.readString();
const type = this.readType(parentStructTypes);
// Mutate the already created structType since when looking for the cycle we compare
// by identity.
fields[i] = {name, type};
}
parentStructTypes.pop();
return structType;
}
}