A more... pragmatic DefaultPointer
This commit is contained in:
parent
12121128a6
commit
8f2da8f8db
|
@ -1,9 +1,10 @@
|
||||||
import { Encoder } from "./encoder";
|
import { Encoder } from "./encoder";
|
||||||
import { Tag } from "./constants";
|
import { Tag } from "./constants";
|
||||||
import { AsPreserve, PreserveOn } from "./symbols";
|
import { AsPreserve, PreserveOn } from "./symbols";
|
||||||
import { DefaultPointer, Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { is, isAnnotated, IsPreservesAnnotated } from "./is";
|
import { is, isAnnotated, IsPreservesAnnotated } from "./is";
|
||||||
import { stringify } from "./text";
|
import { stringify } from "./text";
|
||||||
|
import { DefaultPointer } from "./pointer";
|
||||||
|
|
||||||
export interface Position {
|
export interface Position {
|
||||||
line?: number;
|
line?: number;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Tag } from './constants';
|
import { Tag } from './constants';
|
||||||
import { AsPreserve, PreserveOn } from './symbols';
|
import { AsPreserve, PreserveOn } from './symbols';
|
||||||
import { Encoder, Preservable } from './encoder';
|
import { Encoder, Preservable } from './encoder';
|
||||||
import { DefaultPointer, Value } from './values';
|
import { Value } from './values';
|
||||||
|
import { DefaultPointer } from './pointer';
|
||||||
|
|
||||||
const textEncoder = new TextEncoder();
|
const textEncoder = new TextEncoder();
|
||||||
const textDecoder = new TextDecoder();
|
const textDecoder = new TextDecoder();
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { Tag } from "./constants";
|
||||||
import { FlexMap, FlexSet, _iterMap } from "./flex";
|
import { FlexMap, FlexSet, _iterMap } from "./flex";
|
||||||
import { PreserveOn } from "./symbols";
|
import { PreserveOn } from "./symbols";
|
||||||
import { stringify } from "./text";
|
import { stringify } from "./text";
|
||||||
import { DefaultPointer, Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { Bytes } from './bytes';
|
import { Bytes } from './bytes';
|
||||||
import { fromJS } from "./fromjs";
|
import { fromJS } from "./fromjs";
|
||||||
|
import { DefaultPointer } from "./pointer";
|
||||||
|
|
||||||
export type DictionaryType = 'Dictionary' | 'Set';
|
export type DictionaryType = 'Dictionary' | 'Set';
|
||||||
export const DictionaryType = Symbol.for('DictionaryType');
|
export const DictionaryType = Symbol.for('DictionaryType');
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Encoder, Preservable } from "./encoder";
|
import { Encoder, Preservable } from "./encoder";
|
||||||
import { Tag } from "./constants";
|
import { Tag } from "./constants";
|
||||||
import { AsPreserve, PreserveOn } from "./symbols";
|
import { AsPreserve, PreserveOn } from "./symbols";
|
||||||
import { DefaultPointer, Value } from "./values";
|
import { Value } from "./values";
|
||||||
|
import { DefaultPointer } from "./pointer";
|
||||||
|
|
||||||
export type FloatType = 'Single' | 'Double';
|
export type FloatType = 'Single' | 'Double';
|
||||||
export const FloatType = Symbol.for('FloatType');
|
export const FloatType = Symbol.for('FloatType');
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
import { DefaultPointer } from "./pointer";
|
||||||
import { Bytes } from "./bytes";
|
import { Bytes } from "./bytes";
|
||||||
import { Record, Tuple } from "./record";
|
import { Record, Tuple } from "./record";
|
||||||
import { AsPreserve } from "./symbols";
|
import { AsPreserve } from "./symbols";
|
||||||
import { DefaultPointer, Value } from "./values";
|
import { Value } from "./values";
|
||||||
|
|
||||||
export function fromJS<T = DefaultPointer>(x: any): Value<T> {
|
export function fromJS<T = DefaultPointer>(x: any): Value<T> {
|
||||||
switch (typeof x) {
|
switch (typeof x) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { DefaultPointer } from "./values.js";
|
import type { DefaultPointer } from "./pointer.js";
|
||||||
import type { Annotated } from "./annotated.js";
|
import type { Annotated } from "./annotated.js";
|
||||||
|
|
||||||
export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated');
|
export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated');
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import type { Encoder } from "./encoder";
|
||||||
|
import type { TypedDecoder } from "./decoder";
|
||||||
|
import type { Value } from "./values";
|
||||||
|
|
||||||
|
import { strip } from "./strip";
|
||||||
|
|
||||||
|
export class DefaultPointer {
|
||||||
|
v: Value<DefaultPointer>;
|
||||||
|
|
||||||
|
constructor(v: Value<DefaultPointer>) {
|
||||||
|
this.v = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
equals(other: any, is: (a: any, b: any) => boolean) {
|
||||||
|
return Object.is(other.constructor, this.constructor) && is(this.v, other.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
asPreservesText(): string {
|
||||||
|
return '#!' + this.v.asPreservesText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readDefaultPointer(v: Value<DefaultPointer>): DefaultPointer {
|
||||||
|
return new DefaultPointer(strip(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decodeDefaultPointer(d: TypedDecoder<DefaultPointer>): DefaultPointer {
|
||||||
|
return readDefaultPointer(d.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encodeDefaultPointer(e: Encoder<DefaultPointer>, w: DefaultPointer): void {
|
||||||
|
e.push(w.v);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
|
import { DefaultPointer } from "./pointer";
|
||||||
import { is } from "./is";
|
import { is } from "./is";
|
||||||
import { DefaultPointer, Value } from "./values";
|
import { Value } from "./values";
|
||||||
|
|
||||||
export type Tuple<T> = Array<T> | [T];
|
export type Tuple<T> = Array<T> | [T];
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ export * from './float';
|
||||||
export * from './fold';
|
export * from './fold';
|
||||||
export * from './fromjs';
|
export * from './fromjs';
|
||||||
export * from './is';
|
export * from './is';
|
||||||
|
export * from './pointer';
|
||||||
export * from './reader';
|
export * from './reader';
|
||||||
export * from './record';
|
export * from './record';
|
||||||
export * from './strip';
|
export * from './strip';
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { DefaultPointer, Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { Annotated } from "./annotated";
|
import { Annotated } from "./annotated";
|
||||||
import { Record, Tuple } from "./record";
|
import { Record, Tuple } from "./record";
|
||||||
import { Set, Dictionary } from "./dictionary";
|
import { Set, Dictionary } from "./dictionary";
|
||||||
|
import type { DefaultPointer } from "./pointer";
|
||||||
|
|
||||||
export function unannotate<T = DefaultPointer>(v: Value<T>): Value<T> {
|
export function unannotate<T = DefaultPointer>(v: Value<T>): Value<T> {
|
||||||
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
||||||
|
|
|
@ -4,8 +4,7 @@ import type { Bytes } from './bytes';
|
||||||
import type { DoubleFloat, SingleFloat } from './float';
|
import type { DoubleFloat, SingleFloat } from './float';
|
||||||
import type { Annotated } from './annotated';
|
import type { Annotated } from './annotated';
|
||||||
import type { Set, Dictionary } from './dictionary';
|
import type { Set, Dictionary } from './dictionary';
|
||||||
|
import type { DefaultPointer } from './pointer';
|
||||||
export type DefaultPointer = never;
|
|
||||||
|
|
||||||
export type Value<T = DefaultPointer> =
|
export type Value<T = DefaultPointer> =
|
||||||
| Atom
|
| Atom
|
||||||
|
|
|
@ -11,19 +11,21 @@ import {
|
||||||
Constants,
|
Constants,
|
||||||
TypedDecoder,
|
TypedDecoder,
|
||||||
Encoder,
|
Encoder,
|
||||||
|
DefaultPointer,
|
||||||
|
decodeDefaultPointer,
|
||||||
|
encodeDefaultPointer,
|
||||||
} from '../src/index';
|
} from '../src/index';
|
||||||
const { Tag } = Constants;
|
const { Tag } = Constants;
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
import { decodePointer, encodePointer, Pointer } from './test-utils';
|
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
const _discard = Symbol.for('discard');
|
const _discard = Symbol.for('discard');
|
||||||
const _capture = Symbol.for('capture');
|
const _capture = Symbol.for('capture');
|
||||||
const _observe = Symbol.for('observe');
|
const _observe = Symbol.for('observe');
|
||||||
const Discard = Record.makeConstructor<{}, Pointer>()(_discard, []);
|
const Discard = Record.makeConstructor<{}, DefaultPointer>()(_discard, []);
|
||||||
const Capture = Record.makeConstructor<{pattern: Value<Pointer>}, Pointer>()(_capture, ['pattern']);
|
const Capture = Record.makeConstructor<{pattern: Value<DefaultPointer>}, DefaultPointer>()(_capture, ['pattern']);
|
||||||
const Observe = Record.makeConstructor<{pattern: Value<Pointer>}, Pointer>()(_observe, ['pattern']);
|
const Observe = Record.makeConstructor<{pattern: Value<DefaultPointer>}, DefaultPointer>()(_observe, ['pattern']);
|
||||||
|
|
||||||
describe('record constructors', () => {
|
describe('record constructors', () => {
|
||||||
it('should have constructorInfo', () => {
|
it('should have constructorInfo', () => {
|
||||||
|
@ -152,52 +154,61 @@ describe('encoding and decoding pointers', () => {
|
||||||
|
|
||||||
describe('common test suite', () => {
|
describe('common test suite', () => {
|
||||||
const samples_bin = fs.readFileSync(__dirname + '/../../../../../tests/samples.bin');
|
const samples_bin = fs.readFileSync(__dirname + '/../../../../../tests/samples.bin');
|
||||||
const samples = decodeWithAnnotations(samples_bin, { decodePointer });
|
const samples = decodeWithAnnotations(samples_bin, { decodePointer: decodeDefaultPointer });
|
||||||
|
|
||||||
const TestCases = Record.makeConstructor<{cases: Dictionary<Value<Pointer>, Pointer>}>()(Symbol.for('TestCases'), ['cases']);
|
const TestCases = Record.makeConstructor<{
|
||||||
|
cases: Dictionary<Value<DefaultPointer>, DefaultPointer>
|
||||||
|
}>()(Symbol.for('TestCases'), ['cases']);
|
||||||
type TestCases = ReturnType<typeof TestCases>;
|
type TestCases = ReturnType<typeof TestCases>;
|
||||||
|
|
||||||
function DS(bs: Bytes) {
|
function DS(bs: Bytes) {
|
||||||
return decode(bs, { decodePointer });
|
return decode(bs, { decodePointer: decodeDefaultPointer });
|
||||||
}
|
}
|
||||||
function D(bs: Bytes) {
|
function D(bs: Bytes) {
|
||||||
return decodeWithAnnotations(bs, { decodePointer });
|
return decodeWithAnnotations(bs, { decodePointer: decodeDefaultPointer });
|
||||||
}
|
}
|
||||||
function E(v: Value<Pointer>) {
|
function E(v: Value<DefaultPointer>) {
|
||||||
return encodeWithAnnotations(v, { encodePointer });
|
return encodeWithAnnotations(v, { encodePointer: encodeDefaultPointer });
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExpectedValues {
|
interface ExpectedValues {
|
||||||
[testName: string]: { value: Value<Pointer> } | { forward: Value<Pointer>, back: Value<Pointer> };
|
[testName: string]: ({
|
||||||
|
value: Value<DefaultPointer>;
|
||||||
|
} | {
|
||||||
|
forward: Value<DefaultPointer>;
|
||||||
|
back: Value<DefaultPointer>;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const expectedValues: ExpectedValues = {
|
const expectedValues: ExpectedValues = {
|
||||||
annotation1: { forward: annotate<Pointer>(9, "abc"),
|
annotation1: { forward: annotate<DefaultPointer>(9, "abc"),
|
||||||
back: 9 },
|
back: 9 },
|
||||||
annotation2: { forward: annotate<Pointer>([[], annotate<Pointer>([], "x")], "abc", "def"),
|
annotation2: { forward: annotate<DefaultPointer>([[], annotate<DefaultPointer>([], "x")],
|
||||||
|
"abc",
|
||||||
|
"def"),
|
||||||
back: [[], []] },
|
back: [[], []] },
|
||||||
annotation3: { forward: annotate<Pointer>(5,
|
annotation3: { forward: annotate<DefaultPointer>(5,
|
||||||
annotate<Pointer>(2, 1),
|
annotate<DefaultPointer>(2, 1),
|
||||||
annotate<Pointer>(4, 3)),
|
annotate<DefaultPointer>(4, 3)),
|
||||||
back: 5 },
|
back: 5 },
|
||||||
annotation5: {
|
annotation5: {
|
||||||
forward: annotate<Pointer>(
|
forward: annotate<DefaultPointer>(
|
||||||
Record<symbol, any>(Symbol.for('R'),
|
Record<symbol, any>(Symbol.for('R'),
|
||||||
[annotate<Pointer>(Symbol.for('f'),
|
[annotate<DefaultPointer>(Symbol.for('f'),
|
||||||
Symbol.for('af'))]),
|
Symbol.for('af'))]),
|
||||||
Symbol.for('ar')),
|
Symbol.for('ar')),
|
||||||
back: Record<Value<Pointer>, any>(Symbol.for('R'), [Symbol.for('f')])
|
back: Record<Value<DefaultPointer>, any>(Symbol.for('R'), [Symbol.for('f')])
|
||||||
},
|
},
|
||||||
annotation6: {
|
annotation6: {
|
||||||
forward: Record<Value<Pointer>, any>(
|
forward: Record<Value<DefaultPointer>, any>(
|
||||||
annotate<Pointer>(Symbol.for('R'),
|
annotate<DefaultPointer>(Symbol.for('R'),
|
||||||
Symbol.for('ar')),
|
Symbol.for('ar')),
|
||||||
[annotate<Pointer>(Symbol.for('f'),
|
[annotate<DefaultPointer>(Symbol.for('f'),
|
||||||
Symbol.for('af'))]),
|
Symbol.for('af'))]),
|
||||||
back: Record<symbol, any>(Symbol.for('R'), [Symbol.for('f')])
|
back: Record<symbol, any>(Symbol.for('R'), [Symbol.for('f')])
|
||||||
},
|
},
|
||||||
annotation7: {
|
annotation7: {
|
||||||
forward: annotate<Pointer>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
|
forward: annotate<DefaultPointer>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
|
||||||
back: []
|
back: []
|
||||||
},
|
},
|
||||||
list1: {
|
list1: {
|
||||||
|
@ -214,7 +225,11 @@ describe('common test suite', () => {
|
||||||
|
|
||||||
type Variety = 'normal' | 'nondeterministic' | 'decode';
|
type Variety = 'normal' | 'nondeterministic' | 'decode';
|
||||||
|
|
||||||
function runTestCase(variety: Variety, tName: string, binaryForm: Bytes, annotatedTextForm: Value<Pointer>) {
|
function runTestCase(variety: Variety,
|
||||||
|
tName: string,
|
||||||
|
binaryForm: Bytes,
|
||||||
|
annotatedTextForm: Value<DefaultPointer>)
|
||||||
|
{
|
||||||
describe(tName, () => {
|
describe(tName, () => {
|
||||||
const textForm = strip(annotatedTextForm);
|
const textForm = strip(annotatedTextForm);
|
||||||
const {forward, back} = (function () {
|
const {forward, back} = (function () {
|
||||||
|
@ -241,10 +256,11 @@ describe('common test suite', () => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const tests = peel(TestCases._.cases(peel(samples) as TestCases)) as Dictionary<Value<Pointer>, Pointer>;
|
const tests = (peel(TestCases._.cases(peel(samples) as TestCases)) as
|
||||||
tests.forEach((t0: Value<Pointer>, tName0: Value<Pointer>) => {
|
Dictionary<Value<DefaultPointer>, DefaultPointer>);
|
||||||
|
tests.forEach((t0: Value<DefaultPointer>, tName0: Value<DefaultPointer>) => {
|
||||||
const tName = Symbol.keyFor(strip(tName0) as symbol)!;
|
const tName = Symbol.keyFor(strip(tName0) as symbol)!;
|
||||||
const t = peel(t0) as Record<symbol, any, Pointer>;
|
const t = peel(t0) as Record<symbol, any, DefaultPointer>;
|
||||||
switch (t.label) {
|
switch (t.label) {
|
||||||
case Symbol.for('Test'):
|
case Symbol.for('Test'):
|
||||||
runTestCase('normal', tName, strip(t[0]) as Bytes, t[1]);
|
runTestCase('normal', tName, strip(t[0]) as Bytes, t[1]);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Bytes, Decoder, encode, Reader } from '../src/index';
|
import { Bytes, decodeDefaultPointer, Decoder, encode, encodeDefaultPointer, readDefaultPointer, Reader } from '../src/index';
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
import { decodePointer, encodePointer, readPointer } from './test-utils';
|
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
@ -9,25 +8,25 @@ describe('reading common test suite', () => {
|
||||||
const samples_pr = fs.readFileSync(__dirname + '/../../../../../tests/samples.pr', 'utf-8');
|
const samples_pr = fs.readFileSync(__dirname + '/../../../../../tests/samples.pr', 'utf-8');
|
||||||
|
|
||||||
it('should read equal to decoded binary without annotations', () => {
|
it('should read equal to decoded binary without annotations', () => {
|
||||||
const s1 = new Reader(samples_pr, { decodePointer: readPointer, includeAnnotations: false }).next();
|
const s1 = new Reader(samples_pr, { decodePointer: readDefaultPointer, includeAnnotations: false }).next();
|
||||||
const s2 = new Decoder(samples_bin, { includeAnnotations: false }).withPointerDecoder(
|
const s2 = new Decoder(samples_bin, { includeAnnotations: false }).withPointerDecoder(
|
||||||
decodePointer,
|
decodeDefaultPointer,
|
||||||
d => d.next());
|
d => d.next());
|
||||||
expect(s1).is(s2);
|
expect(s1).is(s2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should read equal to decoded binary with annotations', () => {
|
it('should read equal to decoded binary with annotations', () => {
|
||||||
const s1 = new Reader(samples_pr, { decodePointer: readPointer, includeAnnotations: true }).next();
|
const s1 = new Reader(samples_pr, { decodePointer: readDefaultPointer, includeAnnotations: true }).next();
|
||||||
const s2 = new Decoder(samples_bin, { includeAnnotations: true }).withPointerDecoder(
|
const s2 = new Decoder(samples_bin, { includeAnnotations: true }).withPointerDecoder(
|
||||||
decodePointer,
|
decodeDefaultPointer,
|
||||||
d => d.next());
|
d => d.next());
|
||||||
expect(s1).is(s2);
|
expect(s1).is(s2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should read and encode back to binary with annotations', () => {
|
it('should read and encode back to binary with annotations', () => {
|
||||||
const s = new Reader(samples_pr, { decodePointer: readPointer, includeAnnotations: true }).next();
|
const s = new Reader(samples_pr, { decodePointer: readDefaultPointer, includeAnnotations: true }).next();
|
||||||
const bs = Bytes.toIO(encode(s, {
|
const bs = Bytes.toIO(encode(s, {
|
||||||
encodePointer,
|
encodePointer: encodeDefaultPointer,
|
||||||
includeAnnotations: true,
|
includeAnnotations: true,
|
||||||
canonical: true,
|
canonical: true,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -34,31 +34,3 @@ expect.extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export class Pointer {
|
|
||||||
v: Value<Pointer>;
|
|
||||||
|
|
||||||
constructor(v: Value<Pointer>) {
|
|
||||||
this.v = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
equals(other: any, is: (a: any, b: any) => boolean) {
|
|
||||||
return Object.is(other.constructor, this.constructor) && is(this.v, other.v);
|
|
||||||
}
|
|
||||||
|
|
||||||
asPreservesText(): string {
|
|
||||||
return '#!' + this.v.asPreservesText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readPointer(v: Value<Pointer>): Pointer {
|
|
||||||
return new Pointer(strip(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function decodePointer(d: TypedDecoder<Pointer>): Pointer {
|
|
||||||
return readPointer(d.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
export function encodePointer(e: Encoder<Pointer>, w: Pointer): void {
|
|
||||||
e.push(w.v);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue