mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-11 02:59:34 -06:00
232 lines
6.6 KiB
JavaScript
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;
|
|
}
|
|
}
|