forked from syndicate-lang/preserves
The Great Renaming: Pointer -> Embedded
This commit is contained in:
parent
6fc41ead6f
commit
e4a2503899
|
@ -38,7 +38,7 @@ representations of their keys.[^no-need-for-by-value]
|
||||||
**Other kinds of `Value`.**
|
**Other kinds of `Value`.**
|
||||||
There are no special canonicalization restrictions on
|
There are no special canonicalization restrictions on
|
||||||
`SignedInteger`s, `String`s, `ByteString`s, `Symbol`s, `Boolean`s,
|
`SignedInteger`s, `String`s, `ByteString`s, `Symbol`s, `Boolean`s,
|
||||||
`Float`s, `Double`s, `Record`s, `Sequence`s, or `Pointer`s. The
|
`Float`s, `Double`s, `Record`s, `Sequence`s, or `Embedded`s. The
|
||||||
constraints given for these `Value`s in the [specification][spec]
|
constraints given for these `Value`s in the [specification][spec]
|
||||||
suffice to ensure canonicity.
|
suffice to ensure canonicity.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@preserves/core",
|
"name": "@preserves/core",
|
||||||
"version": "0.14.0",
|
"version": "0.15.0",
|
||||||
"description": "Preserves data serialization format",
|
"description": "Preserves data serialization format",
|
||||||
"homepage": "https://gitlab.com/preserves/preserves",
|
"homepage": "https://gitlab.com/preserves/preserves",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AsPreserve, PreserveOn } from "./symbols";
|
||||||
import { 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 { GenericPointer } from "./pointer";
|
import { GenericEmbedded } from "./embedded";
|
||||||
|
|
||||||
export interface Position {
|
export interface Position {
|
||||||
line?: number;
|
line?: number;
|
||||||
|
@ -53,7 +53,7 @@ export function formatPosition(p: Position | null | string): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Annotated<T = GenericPointer> {
|
export class Annotated<T = GenericEmbedded> {
|
||||||
readonly annotations: Array<Value<T>>;
|
readonly annotations: Array<Value<T>>;
|
||||||
readonly pos: Position | null;
|
readonly pos: Position | null;
|
||||||
readonly item: Value<T>;
|
readonly item: Value<T>;
|
||||||
|
@ -99,17 +99,17 @@ export class Annotated<T = GenericPointer> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isAnnotated<T = GenericPointer>(x: any): x is Annotated<T> {
|
static isAnnotated<T = GenericEmbedded>(x: any): x is Annotated<T> {
|
||||||
return isAnnotated(x);
|
return isAnnotated(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function annotate<T = GenericPointer>(v0: Value<T>, ...anns: Value<T>[]): Annotated<T> {
|
export function annotate<T = GenericEmbedded>(v0: Value<T>, ...anns: Value<T>[]): Annotated<T> {
|
||||||
const v = Annotated.isAnnotated<T>(v0) ? v0 : new Annotated(v0);
|
const v = Annotated.isAnnotated<T>(v0) ? v0 : new Annotated(v0);
|
||||||
anns.forEach((a) => v.annotations.push(a));
|
anns.forEach((a) => v.annotations.push(a));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function position<T = GenericPointer>(v: Value<T>): Position | null {
|
export function position<T = GenericEmbedded>(v: Value<T>): Position | null {
|
||||||
return Annotated.isAnnotated<T>(v) ? v.pos : null;
|
return Annotated.isAnnotated<T>(v) ? v.pos : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ 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 { Value } from './values';
|
import { Value } from './values';
|
||||||
import { GenericPointer } from './pointer';
|
import { GenericEmbedded } from './embedded';
|
||||||
|
|
||||||
const textEncoder = new TextEncoder();
|
const textEncoder = new TextEncoder();
|
||||||
const textDecoder = new TextDecoder();
|
const textDecoder = new TextDecoder();
|
||||||
|
@ -127,7 +127,7 @@ export class Bytes implements Preservable<never> {
|
||||||
return this.asPreservesText();
|
return this.asPreservesText();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AsPreserve]<T = GenericPointer>(): Value<T> {
|
[AsPreserve]<T = GenericEmbedded>(): Value<T> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import type { Compound, Value } from "./values";
|
import type { Compound, Value } from "./values";
|
||||||
import type { GenericPointer } from "./pointer";
|
import type { GenericEmbedded } from "./embedded";
|
||||||
import { Dictionary, Set } from "./dictionary";
|
import { Dictionary, Set } from "./dictionary";
|
||||||
|
|
||||||
export function isCompound<T = GenericPointer>(x: Value<T>): x is Compound<T>
|
export function isCompound<T = GenericEmbedded>(x: Value<T>): x is Compound<T>
|
||||||
{
|
{
|
||||||
return (Array.isArray(x) || Set.isSet(x) || Dictionary.isDictionary(x));
|
return (Array.isArray(x) || Set.isSet(x) || Dictionary.isDictionary(x));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ export enum Tag {
|
||||||
Double,
|
Double,
|
||||||
End,
|
End,
|
||||||
Annotation,
|
Annotation,
|
||||||
Pointer,
|
Embedded,
|
||||||
|
|
||||||
SmallInteger_lo = 0x90,
|
SmallInteger_lo = 0x90,
|
||||||
MediumInteger_lo = 0xa0,
|
MediumInteger_lo = 0xa0,
|
||||||
|
|
|
@ -7,14 +7,14 @@ import { Record } from "./record";
|
||||||
import { Bytes, BytesLike, underlying } from "./bytes";
|
import { Bytes, BytesLike, underlying } from "./bytes";
|
||||||
import { Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { is } from "./is";
|
import { is } from "./is";
|
||||||
import { embed, GenericPointer, Pointer, PointerTypeDecode } from "./pointer";
|
import { embed, GenericEmbedded, Embedded, EmbeddedTypeDecode } from "./embedded";
|
||||||
|
|
||||||
export interface DecoderOptions {
|
export interface DecoderOptions {
|
||||||
includeAnnotations?: boolean;
|
includeAnnotations?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DecoderPointerOptions<T> extends DecoderOptions {
|
export interface DecoderEmbeddedOptions<T> extends DecoderOptions {
|
||||||
pointerDecode?: PointerTypeDecode<T>;
|
embeddedDecode?: EmbeddedTypeDecode<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TypedDecoder<T> {
|
export interface TypedDecoder<T> {
|
||||||
|
@ -25,14 +25,14 @@ export interface TypedDecoder<T> {
|
||||||
|
|
||||||
skip(): void;
|
skip(): void;
|
||||||
next(): Value<T>;
|
next(): Value<T>;
|
||||||
withPointerDecode<S, R>(
|
withEmbeddedDecode<S, R>(
|
||||||
pointerDecode: PointerTypeDecode<S>,
|
embeddedDecode: EmbeddedTypeDecode<S>,
|
||||||
body: (d: TypedDecoder<S>) => R): R;
|
body: (d: TypedDecoder<S>) => R): R;
|
||||||
|
|
||||||
nextBoolean(): boolean | undefined;
|
nextBoolean(): boolean | undefined;
|
||||||
nextFloat(): SingleFloat | undefined;
|
nextFloat(): SingleFloat | undefined;
|
||||||
nextDouble(): DoubleFloat | undefined;
|
nextDouble(): DoubleFloat | undefined;
|
||||||
nextPointer(): Pointer<T> | undefined;
|
nextEmbedded(): Embedded<T> | undefined;
|
||||||
nextSignedInteger(): number | undefined;
|
nextSignedInteger(): number | undefined;
|
||||||
nextString(): string | undefined;
|
nextString(): string | undefined;
|
||||||
nextByteString(): Bytes | undefined;
|
nextByteString(): Bytes | undefined;
|
||||||
|
@ -161,33 +161,33 @@ export class DecoderState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const neverPointerTypeDecode: PointerTypeDecode<never> = {
|
export const neverEmbeddedTypeDecode: EmbeddedTypeDecode<never> = {
|
||||||
decode(_s: DecoderState): never {
|
decode(_s: DecoderState): never {
|
||||||
throw new Error("Pointers not permitted at this point in Preserves document");
|
throw new Error("Embeddeds not permitted at this point in Preserves document");
|
||||||
},
|
},
|
||||||
|
|
||||||
fromValue(_v: Value<GenericPointer>): never {
|
fromValue(_v: Value<GenericEmbedded>): never {
|
||||||
throw new Error("Pointers not permitted at this point in Preserves document");
|
throw new Error("Embeddeds not permitted at this point in Preserves document");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Decoder<T = never> implements TypedDecoder<T> {
|
export class Decoder<T = never> implements TypedDecoder<T> {
|
||||||
state: DecoderState;
|
state: DecoderState;
|
||||||
pointerDecode: PointerTypeDecode<T>;
|
embeddedDecode: EmbeddedTypeDecode<T>;
|
||||||
|
|
||||||
constructor(state: DecoderState, pointerDecode?: PointerTypeDecode<T>);
|
constructor(state: DecoderState, embeddedDecode?: EmbeddedTypeDecode<T>);
|
||||||
constructor(packet?: BytesLike, options?: DecoderPointerOptions<T>);
|
constructor(packet?: BytesLike, options?: DecoderEmbeddedOptions<T>);
|
||||||
constructor(
|
constructor(
|
||||||
packet_or_state: (DecoderState | BytesLike) = new Uint8Array(0),
|
packet_or_state: (DecoderState | BytesLike) = new Uint8Array(0),
|
||||||
options_or_pointerDecode?: (DecoderPointerOptions<T> | PointerTypeDecode<T>))
|
options_or_embeddedDecode?: (DecoderEmbeddedOptions<T> | EmbeddedTypeDecode<T>))
|
||||||
{
|
{
|
||||||
if (packet_or_state instanceof DecoderState) {
|
if (packet_or_state instanceof DecoderState) {
|
||||||
this.state = packet_or_state;
|
this.state = packet_or_state;
|
||||||
this.pointerDecode = (options_or_pointerDecode as PointerTypeDecode<T>) ?? neverPointerTypeDecode;
|
this.embeddedDecode = (options_or_embeddedDecode as EmbeddedTypeDecode<T>) ?? neverEmbeddedTypeDecode;
|
||||||
} else {
|
} else {
|
||||||
const options = (options_or_pointerDecode as DecoderPointerOptions<T>) ?? {};
|
const options = (options_or_embeddedDecode as DecoderEmbeddedOptions<T>) ?? {};
|
||||||
this.state = new DecoderState(packet_or_state, options);
|
this.state = new DecoderState(packet_or_state, options);
|
||||||
this.pointerDecode = options.pointerDecode ?? neverPointerTypeDecode;
|
this.embeddedDecode = options.embeddedDecode ?? neverEmbeddedTypeDecode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ export class Decoder<T = never> implements TypedDecoder<T> {
|
||||||
const v = this.next() as Annotated<T>;
|
const v = this.next() as Annotated<T>;
|
||||||
return this.state.unshiftAnnotation(a, v);
|
return this.state.unshiftAnnotation(a, v);
|
||||||
}
|
}
|
||||||
case Tag.Pointer: return this.state.wrap<T>(embed(this.pointerDecode.decode(this.state)));
|
case Tag.Embedded: return this.state.wrap<T>(embed(this.embeddedDecode.decode(this.state)));
|
||||||
case Tag.SignedInteger: return this.state.wrap<T>(this.state.nextint(this.state.varint()));
|
case Tag.SignedInteger: return this.state.wrap<T>(this.state.nextint(this.state.varint()));
|
||||||
case Tag.String: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())).fromUtf8());
|
case Tag.String: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())).fromUtf8());
|
||||||
case Tag.ByteString: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())));
|
case Tag.ByteString: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())));
|
||||||
|
@ -267,11 +267,11 @@ export class Decoder<T = never> implements TypedDecoder<T> {
|
||||||
this.next();
|
this.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
withPointerDecode<S, R>(
|
withEmbeddedDecode<S, R>(
|
||||||
pointerDecode: PointerTypeDecode<S>,
|
embeddedDecode: EmbeddedTypeDecode<S>,
|
||||||
body: (d: TypedDecoder<S>) => R): R
|
body: (d: TypedDecoder<S>) => R): R
|
||||||
{
|
{
|
||||||
return body(new Decoder(this.state, pointerDecode));
|
return body(new Decoder(this.state, embeddedDecode));
|
||||||
}
|
}
|
||||||
|
|
||||||
skipAnnotations(): void {
|
skipAnnotations(): void {
|
||||||
|
@ -306,10 +306,10 @@ export class Decoder<T = never> implements TypedDecoder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextPointer(): Pointer<T> | undefined {
|
nextEmbedded(): Embedded<T> | undefined {
|
||||||
this.skipAnnotations();
|
this.skipAnnotations();
|
||||||
switch (this.state.nextbyte()) {
|
switch (this.state.nextbyte()) {
|
||||||
case Tag.Pointer: return embed(this.pointerDecode.decode(this.state));
|
case Tag.Embedded: return embed(this.embeddedDecode.decode(this.state));
|
||||||
default: return void 0;
|
default: return void 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,11 +374,11 @@ export class Decoder<T = never> implements TypedDecoder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decode<T>(bs: BytesLike, options: DecoderPointerOptions<T> = {}): Value<T> {
|
export function decode<T>(bs: BytesLike, options: DecoderEmbeddedOptions<T> = {}): Value<T> {
|
||||||
return new Decoder(bs, options).next();
|
return new Decoder(bs, options).next();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeWithAnnotations<T>(bs: BytesLike,
|
export function decodeWithAnnotations<T>(bs: BytesLike,
|
||||||
options: DecoderPointerOptions<T> = {}): Annotated<T> {
|
options: DecoderEmbeddedOptions<T> = {}): Annotated<T> {
|
||||||
return decode(bs, { ... options, includeAnnotations: true }) as Annotated<T>;
|
return decode(bs, { ... options, includeAnnotations: true }) as Annotated<T>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,17 @@ import { PreserveOn } from "./symbols";
|
||||||
import { stringify } from "./text";
|
import { stringify } from "./text";
|
||||||
import { Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { Bytes } from './bytes';
|
import { Bytes } from './bytes';
|
||||||
import { GenericPointer } from "./pointer";
|
import { GenericEmbedded } from "./embedded";
|
||||||
|
|
||||||
export type DictionaryType = 'Dictionary' | 'Set';
|
export type DictionaryType = 'Dictionary' | 'Set';
|
||||||
export const DictionaryType = Symbol.for('DictionaryType');
|
export const DictionaryType = Symbol.for('DictionaryType');
|
||||||
|
|
||||||
export class KeyedDictionary<K extends Value<T>, V, T = GenericPointer> extends FlexMap<K, V> {
|
export class KeyedDictionary<K extends Value<T>, V, T = GenericEmbedded> extends FlexMap<K, V> {
|
||||||
get [DictionaryType](): DictionaryType {
|
get [DictionaryType](): DictionaryType {
|
||||||
return 'Dictionary';
|
return 'Dictionary';
|
||||||
}
|
}
|
||||||
|
|
||||||
static isKeyedDictionary<K extends Value<T>, V, T = GenericPointer>(x: any): x is KeyedDictionary<K, V, T> {
|
static isKeyedDictionary<K extends Value<T>, V, T = GenericEmbedded>(x: any): x is KeyedDictionary<K, V, T> {
|
||||||
return x?.[DictionaryType] === 'Dictionary';
|
return x?.[DictionaryType] === 'Dictionary';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export class KeyedDictionary<K extends Value<T>, V, T = GenericPointer> extends
|
||||||
super(canonicalString, items);
|
super(canonicalString, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
mapEntries<W, S extends Value<R>, R = GenericPointer>(f: (entry: [K, V]) => [S, W]): KeyedDictionary<S, W, R> {
|
mapEntries<W, S extends Value<R>, R = GenericEmbedded>(f: (entry: [K, V]) => [S, W]): KeyedDictionary<S, W, R> {
|
||||||
const result = new KeyedDictionary<S, W, R>();
|
const result = new KeyedDictionary<S, W, R>();
|
||||||
for (let oldEntry of this.entries()) {
|
for (let oldEntry of this.entries()) {
|
||||||
const newEntry = f(oldEntry);
|
const newEntry = f(oldEntry);
|
||||||
|
@ -74,18 +74,18 @@ export class KeyedDictionary<K extends Value<T>, V, T = GenericPointer> extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Dictionary<T = GenericPointer, V = Value<T>> extends KeyedDictionary<Value<T>, V, T> {
|
export class Dictionary<T = GenericEmbedded, V = Value<T>> extends KeyedDictionary<Value<T>, V, T> {
|
||||||
static isDictionary<T = GenericPointer, V = Value<T>>(x: any): x is Dictionary<T, V> {
|
static isDictionary<T = GenericEmbedded, V = Value<T>>(x: any): x is Dictionary<T, V> {
|
||||||
return x?.[DictionaryType] === 'Dictionary';
|
return x?.[DictionaryType] === 'Dictionary';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class KeyedSet<K extends Value<T>, T = GenericPointer> extends FlexSet<K> {
|
export class KeyedSet<K extends Value<T>, T = GenericEmbedded> extends FlexSet<K> {
|
||||||
get [DictionaryType](): DictionaryType {
|
get [DictionaryType](): DictionaryType {
|
||||||
return 'Set';
|
return 'Set';
|
||||||
}
|
}
|
||||||
|
|
||||||
static isKeyedSet<K extends Value<T>, T = GenericPointer>(x: any): x is KeyedSet<K, T> {
|
static isKeyedSet<K extends Value<T>, T = GenericEmbedded>(x: any): x is KeyedSet<K, T> {
|
||||||
return x?.[DictionaryType] === 'Set';
|
return x?.[DictionaryType] === 'Set';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ export class KeyedSet<K extends Value<T>, T = GenericPointer> extends FlexSet<K>
|
||||||
super(canonicalString, items);
|
super(canonicalString, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
map<S extends Value<R>, R = GenericPointer>(f: (value: K) => S): KeyedSet<S, R> {
|
map<S extends Value<R>, R = GenericEmbedded>(f: (value: K) => S): KeyedSet<S, R> {
|
||||||
return new KeyedSet(_iterMap(this[Symbol.iterator](), f));
|
return new KeyedSet(_iterMap(this[Symbol.iterator](), f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,8 +130,8 @@ export class KeyedSet<K extends Value<T>, T = GenericPointer> extends FlexSet<K>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Set<T = GenericPointer> extends KeyedSet<Value<T>, T> {
|
export class Set<T = GenericEmbedded> extends KeyedSet<Value<T>, T> {
|
||||||
static isSet<T = GenericPointer>(x: any): x is Set<T> {
|
static isSet<T = GenericEmbedded>(x: any): x is Set<T> {
|
||||||
return x?.[DictionaryType] === 'Set';
|
return x?.[DictionaryType] === 'Set';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,19 @@ import type { EncoderState } from "./encoder";
|
||||||
import type { DecoderState } from "./decoder";
|
import type { DecoderState } from "./decoder";
|
||||||
import type { Value } from "./values";
|
import type { Value } from "./values";
|
||||||
|
|
||||||
export type PointerTypeEncode<T> = {
|
export type EmbeddedTypeEncode<T> = {
|
||||||
encode(s: EncoderState, v: T): void;
|
encode(s: EncoderState, v: T): void;
|
||||||
toValue(v: T): Value<GenericPointer>;
|
toValue(v: T): Value<GenericEmbedded>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PointerTypeDecode<T> = {
|
export type EmbeddedTypeDecode<T> = {
|
||||||
decode(s: DecoderState): T;
|
decode(s: DecoderState): T;
|
||||||
fromValue(v: Value<GenericPointer>): T;
|
fromValue(v: Value<GenericEmbedded>): T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PointerType<T> = PointerTypeEncode<T> & PointerTypeDecode<T>;
|
export type EmbeddedType<T> = EmbeddedTypeEncode<T> & EmbeddedTypeDecode<T>;
|
||||||
|
|
||||||
export class Pointer<T> {
|
export class Embedded<T> {
|
||||||
embeddedValue: T;
|
embeddedValue: T;
|
||||||
|
|
||||||
constructor(embeddedValue: T) {
|
constructor(embeddedValue: T) {
|
||||||
|
@ -22,7 +22,7 @@ export class Pointer<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: any, is: (a: any, b: any) => boolean) {
|
equals(other: any, is: (a: any, b: any) => boolean) {
|
||||||
return isPointer<T>(other) && is(this.embeddedValue, other.embeddedValue);
|
return isEmbedded<T>(other) && is(this.embeddedValue, other.embeddedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
asPreservesText(): string {
|
asPreservesText(): string {
|
||||||
|
@ -30,15 +30,15 @@ export class Pointer<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function embed<T>(embeddedValue: T): Pointer<T> {
|
export function embed<T>(embeddedValue: T): Embedded<T> {
|
||||||
return new Pointer(embeddedValue);
|
return new Embedded(embeddedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPointer<T>(v: Value<T>): v is Pointer<T> {
|
export function isEmbedded<T>(v: Value<T>): v is Embedded<T> {
|
||||||
return typeof v === 'object' && 'embeddedValue' in v;
|
return typeof v === 'object' && 'embeddedValue' in v;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GenericPointer {
|
export class GenericEmbedded {
|
||||||
generic: Value;
|
generic: Value;
|
||||||
|
|
||||||
constructor(generic: Value) {
|
constructor(generic: Value) {
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { GenericEmbedded, EmbeddedType, EmbeddedTypeDecode, EmbeddedTypeEncode } from "./embedded";
|
||||||
|
import { Encoder, EncoderState, identityEmbeddedTypeEncode } from "./encoder";
|
||||||
|
import { genericEmbeddedTypeDecode } from "./reader";
|
||||||
|
import { Value } from "./values";
|
||||||
|
import { DecoderState, neverEmbeddedTypeDecode } from "./decoder";
|
||||||
|
|
||||||
|
export const genericEmbeddedTypeEncode: EmbeddedTypeEncode<GenericEmbedded> = {
|
||||||
|
encode(s: EncoderState, v: GenericEmbedded): void {
|
||||||
|
new Encoder(s, this).push(v.generic);
|
||||||
|
},
|
||||||
|
|
||||||
|
toValue(v: GenericEmbedded): Value<GenericEmbedded> {
|
||||||
|
return v.generic;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const genericEmbeddedType: EmbeddedType<GenericEmbedded> =
|
||||||
|
Object.assign({},
|
||||||
|
genericEmbeddedTypeDecode,
|
||||||
|
genericEmbeddedTypeEncode);
|
||||||
|
|
||||||
|
export const neverEmbeddedTypeEncode: EmbeddedTypeEncode<never> = {
|
||||||
|
encode(_s: EncoderState, _v: never): void {
|
||||||
|
throw new Error("Embeddeds not permitted encoding Preserves document");
|
||||||
|
},
|
||||||
|
|
||||||
|
toValue(_v: never): Value<GenericEmbedded> {
|
||||||
|
throw new Error("Embeddeds not permitted encoding Preserves document");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const neverEmbeddedType: EmbeddedType<never> =
|
||||||
|
Object.assign({},
|
||||||
|
neverEmbeddedTypeDecode,
|
||||||
|
neverEmbeddedTypeEncode);
|
||||||
|
|
||||||
|
export const identityEmbeddedTypeDecode: EmbeddedTypeDecode<any> = {
|
||||||
|
decode(_s: DecoderState): any {
|
||||||
|
throw new Error("Cannot decode identityEmbeddedType");
|
||||||
|
},
|
||||||
|
|
||||||
|
fromValue(_v: Value<GenericEmbedded>): any {
|
||||||
|
throw new Error("Cannot decode identityEmbeddedType");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const identityEmbeddedType: EmbeddedType<any> =
|
||||||
|
Object.assign({},
|
||||||
|
identityEmbeddedTypeDecode,
|
||||||
|
identityEmbeddedTypeEncode);
|
|
@ -4,7 +4,7 @@ import { Value } from "./values";
|
||||||
import { PreserveOn } from "./symbols";
|
import { PreserveOn } from "./symbols";
|
||||||
import { EncodeError } from "./codec";
|
import { EncodeError } from "./codec";
|
||||||
import { Record, Tuple } from "./record";
|
import { Record, Tuple } from "./record";
|
||||||
import { GenericPointer, PointerTypeEncode } from "./pointer";
|
import { GenericEmbedded, EmbeddedTypeEncode } from "./embedded";
|
||||||
|
|
||||||
export type Encodable<T> =
|
export type Encodable<T> =
|
||||||
Value<T> | Preservable<T> | Iterable<Value<T>> | ArrayBufferView;
|
Value<T> | Preservable<T> | Iterable<Value<T>> | ArrayBufferView;
|
||||||
|
@ -22,8 +22,8 @@ export interface EncoderOptions {
|
||||||
includeAnnotations?: boolean;
|
includeAnnotations?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EncoderPointerOptions<T> extends EncoderOptions {
|
export interface EncoderEmbeddedOptions<T> extends EncoderOptions {
|
||||||
pointerEncode?: PointerTypeEncode<T>;
|
embeddedEncode?: EmbeddedTypeEncode<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asLatin1(bs: Uint8Array): string {
|
export function asLatin1(bs: Uint8Array): string {
|
||||||
|
@ -36,7 +36,7 @@ function isIterable<T>(v: any): v is Iterable<T> {
|
||||||
|
|
||||||
let _nextId = 0;
|
let _nextId = 0;
|
||||||
const _registry = new WeakMap<object, number>();
|
const _registry = new WeakMap<object, number>();
|
||||||
export function pointerId(v: any): number {
|
export function embeddedId(v: any): number {
|
||||||
let id = _registry.get(v);
|
let id = _registry.get(v);
|
||||||
if (id === void 0) {
|
if (id === void 0) {
|
||||||
id = _nextId++;
|
id = _nextId++;
|
||||||
|
@ -45,13 +45,13 @@ export function pointerId(v: any): number {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const identityPointerTypeEncode: PointerTypeEncode<any> = {
|
export const identityEmbeddedTypeEncode: EmbeddedTypeEncode<any> = {
|
||||||
encode(s: EncoderState, v: any): void {
|
encode(s: EncoderState, v: any): void {
|
||||||
new Encoder(s, this).push(pointerId(v));
|
new Encoder(s, this).push(embeddedId(v));
|
||||||
},
|
},
|
||||||
|
|
||||||
toValue(v: any): Value<GenericPointer> {
|
toValue(v: any): Value<GenericEmbedded> {
|
||||||
return pointerId(v);
|
return embeddedId(v);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,28 +159,28 @@ export class EncoderState {
|
||||||
|
|
||||||
export class Encoder<T = object> {
|
export class Encoder<T = object> {
|
||||||
state: EncoderState;
|
state: EncoderState;
|
||||||
pointerEncode: PointerTypeEncode<T>;
|
embeddedEncode: EmbeddedTypeEncode<T>;
|
||||||
|
|
||||||
constructor(options: EncoderPointerOptions<T>);
|
constructor(options: EncoderEmbeddedOptions<T>);
|
||||||
constructor(state: EncoderState, pointerEncode?: PointerTypeEncode<T>);
|
constructor(state: EncoderState, embeddedEncode?: EmbeddedTypeEncode<T>);
|
||||||
constructor(
|
constructor(
|
||||||
state_or_options: (EncoderState | EncoderPointerOptions<T>) = {},
|
state_or_options: (EncoderState | EncoderEmbeddedOptions<T>) = {},
|
||||||
pointerEncode?: PointerTypeEncode<T>)
|
embeddedEncode?: EmbeddedTypeEncode<T>)
|
||||||
{
|
{
|
||||||
if (state_or_options instanceof EncoderState) {
|
if (state_or_options instanceof EncoderState) {
|
||||||
this.state = state_or_options;
|
this.state = state_or_options;
|
||||||
this.pointerEncode = pointerEncode ?? identityPointerTypeEncode;
|
this.embeddedEncode = embeddedEncode ?? identityEmbeddedTypeEncode;
|
||||||
} else {
|
} else {
|
||||||
this.state = new EncoderState(state_or_options);
|
this.state = new EncoderState(state_or_options);
|
||||||
this.pointerEncode = state_or_options.pointerEncode ?? identityPointerTypeEncode;
|
this.embeddedEncode = state_or_options.embeddedEncode ?? identityEmbeddedTypeEncode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
withPointerEncode<S>(
|
withEmbeddedEncode<S>(
|
||||||
pointerEncode: PointerTypeEncode<S>,
|
embeddedEncode: EmbeddedTypeEncode<S>,
|
||||||
body: (e: Encoder<S>) => void): this
|
body: (e: Encoder<S>) => void): this
|
||||||
{
|
{
|
||||||
body(new Encoder(this.state, pointerEncode));
|
body(new Encoder(this.state, embeddedEncode));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +252,8 @@ export class Encoder<T = object> {
|
||||||
this.encodevalues(Tag.Sequence, v as Iterable<Value<T>>);
|
this.encodevalues(Tag.Sequence, v as Iterable<Value<T>>);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.state.emitbyte(Tag.Pointer);
|
this.state.emitbyte(Tag.Embedded);
|
||||||
this.pointerEncode.encode(this.state, v.embeddedValue);
|
this.embeddedEncode.encode(this.state, v.embeddedValue);
|
||||||
}
|
}
|
||||||
return this; // for chaining
|
return this; // for chaining
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ export class Encoder<T = object> {
|
||||||
|
|
||||||
export function encode<T>(
|
export function encode<T>(
|
||||||
v: Encodable<T>,
|
v: Encodable<T>,
|
||||||
options: EncoderPointerOptions<T> = {}): Bytes
|
options: EncoderEmbeddedOptions<T> = {}): Bytes
|
||||||
{
|
{
|
||||||
return new Encoder(options).push(v).contents();
|
return new Encoder(options).push(v).contents();
|
||||||
}
|
}
|
||||||
|
@ -269,9 +269,9 @@ export function encode<T>(
|
||||||
const _canonicalEncoder = new Encoder({ canonical: true });
|
const _canonicalEncoder = new Encoder({ canonical: true });
|
||||||
let _usingCanonicalEncoder = false;
|
let _usingCanonicalEncoder = false;
|
||||||
|
|
||||||
export function canonicalEncode(v: Encodable<never>, options?: EncoderPointerOptions<never>): Bytes;
|
export function canonicalEncode(v: Encodable<never>, options?: EncoderEmbeddedOptions<never>): Bytes;
|
||||||
export function canonicalEncode(v: Encodable<any>, options?: EncoderPointerOptions<any>): Bytes;
|
export function canonicalEncode(v: Encodable<any>, options?: EncoderEmbeddedOptions<any>): Bytes;
|
||||||
export function canonicalEncode(v: any, options?: EncoderPointerOptions<any>): Bytes {
|
export function canonicalEncode(v: any, options?: EncoderEmbeddedOptions<any>): Bytes {
|
||||||
if (options === void 0 && !_usingCanonicalEncoder) {
|
if (options === void 0 && !_usingCanonicalEncoder) {
|
||||||
_usingCanonicalEncoder = true;
|
_usingCanonicalEncoder = true;
|
||||||
const bs = _canonicalEncoder.push(v).contents();
|
const bs = _canonicalEncoder.push(v).contents();
|
||||||
|
@ -294,6 +294,6 @@ export function canonicalString(v: Encodable<any>): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodeWithAnnotations<T>(v: Encodable<T>,
|
export function encodeWithAnnotations<T>(v: Encodable<T>,
|
||||||
options: EncoderPointerOptions<T> = {}): Bytes {
|
options: EncoderEmbeddedOptions<T> = {}): Bytes {
|
||||||
return encode(v, { ... options, includeAnnotations: true });
|
return encode(v, { ... options, includeAnnotations: true });
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Encoder, Preservable } from "./encoder";
|
||||||
import { Tag } from "./constants";
|
import { Tag } from "./constants";
|
||||||
import { AsPreserve, PreserveOn } from "./symbols";
|
import { AsPreserve, PreserveOn } from "./symbols";
|
||||||
import { Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { GenericPointer } from "./pointer";
|
import { GenericEmbedded } from "./embedded";
|
||||||
|
|
||||||
export type FloatType = 'Single' | 'Double';
|
export type FloatType = 'Single' | 'Double';
|
||||||
export const FloatType = Symbol.for('FloatType');
|
export const FloatType = Symbol.for('FloatType');
|
||||||
|
@ -45,7 +45,7 @@ export function floatValue(f: any): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SingleFloat extends Float implements Preservable<never> {
|
export class SingleFloat extends Float implements Preservable<never> {
|
||||||
[AsPreserve]<T = GenericPointer>(): Value<T> {
|
[AsPreserve]<T = GenericEmbedded>(): Value<T> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ export function Single(value: number | Float): SingleFloat {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DoubleFloat extends Float implements Preservable<never> {
|
export class DoubleFloat extends Float implements Preservable<never> {
|
||||||
[AsPreserve]<T = GenericPointer>(): Value<T> {
|
[AsPreserve]<T = GenericEmbedded>(): Value<T> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Value } from "./values";
|
||||||
import { Set, Dictionary } from "./dictionary";
|
import { Set, Dictionary } from "./dictionary";
|
||||||
import { annotate, Annotated } from "./annotated";
|
import { annotate, Annotated } from "./annotated";
|
||||||
import { Double, Float, Single } from "./float";
|
import { Double, Float, Single } from "./float";
|
||||||
import { Pointer } from "./pointer";
|
import { Embedded } from "./embedded";
|
||||||
|
|
||||||
export type Fold<T, R = Value<T>> = (v: Value<T>) => R;
|
export type Fold<T, R = Value<T>> = (v: Value<T>) => R;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export interface FoldMethods<T, R> {
|
||||||
|
|
||||||
annotated(a: Annotated<T>, k: Fold<T, R>): R;
|
annotated(a: Annotated<T>, k: Fold<T, R>): R;
|
||||||
|
|
||||||
pointer(t: Pointer<T>, k: Fold<T, R>): R;
|
embedded(t: Embedded<T>, k: Fold<T, R>): R;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> {
|
export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> {
|
||||||
|
@ -64,11 +64,11 @@ export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> {
|
||||||
annotated(a: Annotated<T>, k: Fold<T, Value<R>>): Value<R> {
|
annotated(a: Annotated<T>, k: Fold<T, Value<R>>): Value<R> {
|
||||||
return annotate(k(a.item), ...a.annotations.map(k));
|
return annotate(k(a.item), ...a.annotations.map(k));
|
||||||
}
|
}
|
||||||
abstract pointer(t: Pointer<T>, k: Fold<T, Value<R>>): Value<R>;
|
abstract embedded(t: Embedded<T>, k: Fold<T, Value<R>>): Value<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IdentityFold<T> extends ValueFold<T, T> {
|
export class IdentityFold<T> extends ValueFold<T, T> {
|
||||||
pointer(t: Pointer<T>, _k: Fold<T, Value<T>>): Value<T> {
|
embedded(t: Embedded<T>, _k: Fold<T, Value<T>>): Value<T> {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ export class MapFold<T, R> extends ValueFold<T, R> {
|
||||||
this.f = f;
|
this.f = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer(t: Pointer<T>, _k: Fold<T, Value<R>>): Value<R> {
|
embedded(t: Embedded<T>, _k: Fold<T, Value<R>>): Value<R> {
|
||||||
return this.f(t.embeddedValue);
|
return this.f(t.embeddedValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ export function fold<T, R>(v: Value<T>, o: FoldMethods<T, R>): R {
|
||||||
} else if (Float.isDouble(v)) {
|
} else if (Float.isDouble(v)) {
|
||||||
return o.double(v.value);
|
return o.double(v.value);
|
||||||
} else {
|
} else {
|
||||||
return o.pointer(v, walk);
|
return o.embedded(v, walk);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
((_v: never): never => { throw new Error("Internal error"); })(v);
|
((_v: never): never => { throw new Error("Internal error"); })(v);
|
||||||
|
@ -131,7 +131,7 @@ export function fold<T, R>(v: Value<T>, o: FoldMethods<T, R>): R {
|
||||||
return walk(v);
|
return walk(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapPointers<T, R>(
|
export function mapEmbeddeds<T, R>(
|
||||||
v: Value<T>,
|
v: Value<T>,
|
||||||
f: (t: T) => Value<R>,
|
f: (t: T) => Value<R>,
|
||||||
): Value<R>
|
): Value<R>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { embed, GenericPointer } from "./pointer";
|
import { embed, GenericEmbedded } from "./embedded";
|
||||||
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 { Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { Dictionary, Set } from "./dictionary";
|
import { Dictionary, Set } from "./dictionary";
|
||||||
|
|
||||||
export function fromJS<T = GenericPointer>(x: any): Value<T> {
|
export function fromJS<T = GenericEmbedded>(x: any): Value<T> {
|
||||||
switch (typeof x) {
|
switch (typeof x) {
|
||||||
case 'number':
|
case 'number':
|
||||||
if (!Number.isInteger(x)) {
|
if (!Number.isInteger(x)) {
|
||||||
|
@ -61,11 +61,11 @@ export function fromJS<T = GenericPointer>(x: any): Value<T> {
|
||||||
|
|
||||||
declare module "./dictionary" {
|
declare module "./dictionary" {
|
||||||
namespace Dictionary {
|
namespace Dictionary {
|
||||||
export function fromJS<T = GenericPointer, V = GenericPointer>(x: object): Dictionary<T, Value<V>>;
|
export function fromJS<T = GenericEmbedded, V = GenericEmbedded>(x: object): Dictionary<T, Value<V>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary.fromJS = function <T = GenericPointer, V = GenericPointer>(x: object): Dictionary<T, Value<V>> {
|
Dictionary.fromJS = function <T = GenericEmbedded, V = GenericEmbedded>(x: object): Dictionary<T, Value<V>> {
|
||||||
if (Dictionary.isDictionary<T, Value<V>>(x)) return x;
|
if (Dictionary.isDictionary<T, Value<V>>(x)) return x;
|
||||||
const d = new Dictionary<T, Value<V>>();
|
const d = new Dictionary<T, Value<V>>();
|
||||||
Object.entries(x).forEach(([key, value]) => d.set(key, fromJS(value)));
|
Object.entries(x).forEach(([key, value]) => d.set(key, fromJS(value)));
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import type { GenericPointer } from "./pointer";
|
import type { GenericEmbedded } from "./embedded";
|
||||||
import type { Annotated } from "./annotated";
|
import type { Annotated } from "./annotated";
|
||||||
|
|
||||||
export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated');
|
export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated');
|
||||||
|
|
||||||
export function isAnnotated<T = GenericPointer>(x: any): x is Annotated<T>
|
export function isAnnotated<T = GenericEmbedded>(x: any): x is Annotated<T>
|
||||||
{
|
{
|
||||||
return !!x?.[IsPreservesAnnotated];
|
return !!x?.[IsPreservesAnnotated];
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@ import { Value } from "./values";
|
||||||
import { Set, Dictionary } from "./dictionary";
|
import { Set, Dictionary } from "./dictionary";
|
||||||
import { Annotated } from "./annotated";
|
import { Annotated } from "./annotated";
|
||||||
import { unannotate } from "./strip";
|
import { unannotate } from "./strip";
|
||||||
import { embed, isPointer, Pointer } from "./pointer";
|
import { embed, isEmbedded, Embedded } from "./embedded";
|
||||||
|
|
||||||
export function merge<T>(
|
export function merge<T>(
|
||||||
mergePointers: (a: T, b: T) => T | undefined,
|
mergeEmbeddeds: (a: T, b: T) => T | undefined,
|
||||||
item0: Value<T>,
|
item0: Value<T>,
|
||||||
... items: Array<Value<T>>): Value<T>
|
... items: Array<Value<T>>): Value<T>
|
||||||
{
|
{
|
||||||
|
@ -54,9 +54,9 @@ export function merge<T>(
|
||||||
return walk(a, unannotate(b));
|
return walk(a, unannotate(b));
|
||||||
},
|
},
|
||||||
|
|
||||||
pointer(t: Pointer<T>) {
|
embedded(t: Embedded<T>) {
|
||||||
if (!isPointer<T>(b)) die();
|
if (!isEmbedded<T>(b)) die();
|
||||||
const r = mergePointers(t.embeddedValue, b.embeddedValue);
|
const r = mergeEmbeddeds(t.embeddedValue, b.embeddedValue);
|
||||||
if (r === void 0) die();
|
if (r === void 0) die();
|
||||||
return embed(r);
|
return embed(r);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
import { GenericPointer, PointerType, PointerTypeDecode, PointerTypeEncode } from "./pointer";
|
|
||||||
import { Encoder, EncoderState, identityPointerTypeEncode } from "./encoder";
|
|
||||||
import { genericPointerTypeDecode } from "./reader";
|
|
||||||
import { Value } from "./values";
|
|
||||||
import { DecoderState, neverPointerTypeDecode } from "./decoder";
|
|
||||||
|
|
||||||
export const genericPointerTypeEncode: PointerTypeEncode<GenericPointer> = {
|
|
||||||
encode(s: EncoderState, v: GenericPointer): void {
|
|
||||||
new Encoder(s, this).push(v.generic);
|
|
||||||
},
|
|
||||||
|
|
||||||
toValue(v: GenericPointer): Value<GenericPointer> {
|
|
||||||
return v.generic;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const genericPointerType: PointerType<GenericPointer> =
|
|
||||||
Object.assign({},
|
|
||||||
genericPointerTypeDecode,
|
|
||||||
genericPointerTypeEncode);
|
|
||||||
|
|
||||||
export const neverPointerTypeEncode: PointerTypeEncode<never> = {
|
|
||||||
encode(_s: EncoderState, _v: never): void {
|
|
||||||
throw new Error("Pointers not permitted encoding Preserves document");
|
|
||||||
},
|
|
||||||
|
|
||||||
toValue(_v: never): Value<GenericPointer> {
|
|
||||||
throw new Error("Pointers not permitted encoding Preserves document");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const neverPointerType: PointerType<never> =
|
|
||||||
Object.assign({},
|
|
||||||
neverPointerTypeDecode,
|
|
||||||
neverPointerTypeEncode);
|
|
||||||
|
|
||||||
export const identityPointerTypeDecode: PointerTypeDecode<any> = {
|
|
||||||
decode(_s: DecoderState): any {
|
|
||||||
throw new Error("Cannot decode identityPointerType");
|
|
||||||
},
|
|
||||||
|
|
||||||
fromValue(_v: Value<GenericPointer>): any {
|
|
||||||
throw new Error("Cannot decode identityPointerType");
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const identityPointerType: PointerType<any> =
|
|
||||||
Object.assign({},
|
|
||||||
identityPointerTypeDecode,
|
|
||||||
identityPointerTypeEncode);
|
|
|
@ -5,12 +5,12 @@ import { DecodeError, ShortPacket } from './codec';
|
||||||
import { Dictionary, Set } from './dictionary';
|
import { Dictionary, Set } from './dictionary';
|
||||||
import { strip, unannotate } from './strip';
|
import { strip, unannotate } from './strip';
|
||||||
import { Bytes, unhexDigit } from './bytes';
|
import { Bytes, unhexDigit } from './bytes';
|
||||||
import { decode, Decoder, DecoderState, neverPointerTypeDecode } from './decoder';
|
import { decode, Decoder, DecoderState, neverEmbeddedTypeDecode } from './decoder';
|
||||||
import { Record } from './record';
|
import { Record } from './record';
|
||||||
import { Annotated, newPosition, Position, updatePosition } from './annotated';
|
import { Annotated, newPosition, Position, updatePosition } from './annotated';
|
||||||
import { Double, DoubleFloat, Single, SingleFloat } from './float';
|
import { Double, DoubleFloat, Single, SingleFloat } from './float';
|
||||||
import { stringify } from './text';
|
import { stringify } from './text';
|
||||||
import { embed, GenericPointer, PointerTypeDecode } from './pointer';
|
import { embed, GenericEmbedded, EmbeddedTypeDecode } from './embedded';
|
||||||
|
|
||||||
export interface ReaderStateOptions {
|
export interface ReaderStateOptions {
|
||||||
includeAnnotations?: boolean;
|
includeAnnotations?: boolean;
|
||||||
|
@ -18,7 +18,7 @@ export interface ReaderStateOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReaderOptions<T> extends ReaderStateOptions {
|
export interface ReaderOptions<T> extends ReaderStateOptions {
|
||||||
pointerDecode?: PointerTypeDecode<T>;
|
embeddedDecode?: EmbeddedTypeDecode<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type IntOrFloat = 'int' | 'float';
|
type IntOrFloat = 'int' | 'float';
|
||||||
|
@ -275,33 +275,33 @@ export class ReaderState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const genericPointerTypeDecode: PointerTypeDecode<GenericPointer> = {
|
export const genericEmbeddedTypeDecode: EmbeddedTypeDecode<GenericEmbedded> = {
|
||||||
decode(s: DecoderState): GenericPointer {
|
decode(s: DecoderState): GenericEmbedded {
|
||||||
return new GenericPointer(new Decoder(s, this).next());
|
return new GenericEmbedded(new Decoder(s, this).next());
|
||||||
},
|
},
|
||||||
|
|
||||||
fromValue(v: Value<GenericPointer>): GenericPointer {
|
fromValue(v: Value<GenericEmbedded>): GenericEmbedded {
|
||||||
return new GenericPointer(strip(v));
|
return new GenericEmbedded(strip(v));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Reader<T> {
|
export class Reader<T> {
|
||||||
state: ReaderState;
|
state: ReaderState;
|
||||||
pointerType: PointerTypeDecode<T>;
|
embeddedType: EmbeddedTypeDecode<T>;
|
||||||
|
|
||||||
constructor(state: ReaderState, pointerType: PointerTypeDecode<T>);
|
constructor(state: ReaderState, embeddedType: EmbeddedTypeDecode<T>);
|
||||||
constructor(buffer: string, options?: ReaderOptions<T>);
|
constructor(buffer: string, options?: ReaderOptions<T>);
|
||||||
constructor(
|
constructor(
|
||||||
state_or_buffer: (ReaderState | string) = '',
|
state_or_buffer: (ReaderState | string) = '',
|
||||||
pointerType_or_options?: (PointerTypeDecode<T> | ReaderOptions<T>))
|
embeddedType_or_options?: (EmbeddedTypeDecode<T> | ReaderOptions<T>))
|
||||||
{
|
{
|
||||||
if (state_or_buffer instanceof ReaderState) {
|
if (state_or_buffer instanceof ReaderState) {
|
||||||
this.state = state_or_buffer;
|
this.state = state_or_buffer;
|
||||||
this.pointerType = pointerType_or_options as PointerTypeDecode<T>;
|
this.embeddedType = embeddedType_or_options as EmbeddedTypeDecode<T>;
|
||||||
} else {
|
} else {
|
||||||
const options = (pointerType_or_options as ReaderOptions<T>) ?? {};
|
const options = (embeddedType_or_options as ReaderOptions<T>) ?? {};
|
||||||
this.state = new ReaderState(state_or_buffer, options);
|
this.state = new ReaderState(state_or_buffer, options);
|
||||||
this.pointerType = options.pointerDecode ?? neverPointerTypeDecode;
|
this.embeddedType = options.embeddedDecode ?? neverEmbeddedTypeDecode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,12 +388,12 @@ export class Reader<T> {
|
||||||
if (!Bytes.isBytes(bs)) this.state.error('ByteString must follow #=',
|
if (!Bytes.isBytes(bs)) this.state.error('ByteString must follow #=',
|
||||||
startPos);
|
startPos);
|
||||||
return decode<T>(bs, {
|
return decode<T>(bs, {
|
||||||
pointerDecode: this.pointerType,
|
embeddedDecode: this.embeddedType,
|
||||||
includeAnnotations: this.state.options.includeAnnotations,
|
includeAnnotations: this.state.options.includeAnnotations,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
case '!': return embed(this.pointerType.fromValue(
|
case '!': return embed(this.embeddedType.fromValue(
|
||||||
new Reader<GenericPointer>(this.state, genericPointerTypeDecode).next()));
|
new Reader<GenericEmbedded>(this.state, genericEmbeddedTypeDecode).next()));
|
||||||
default:
|
default:
|
||||||
this.state.error(`Invalid # syntax: ${c}`, startPos);
|
this.state.error(`Invalid # syntax: ${c}`, startPos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { GenericPointer } from "./pointer";
|
import { GenericEmbedded } from "./embedded";
|
||||||
import { is } from "./is";
|
import { is } from "./is";
|
||||||
import { Value } from "./values";
|
import { Value } from "./values";
|
||||||
|
|
||||||
export type Tuple<T> = Array<T> | [T];
|
export type Tuple<T> = Array<T> | [T];
|
||||||
|
|
||||||
export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>
|
export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>
|
||||||
= FieldsType & { label: LabelType };
|
= FieldsType & { label: LabelType };
|
||||||
|
|
||||||
export type RecordGetters<Fs, R> = {
|
export type RecordGetters<Fs, R> = {
|
||||||
|
@ -14,14 +14,14 @@ export type RecordGetters<Fs, R> = {
|
||||||
export type CtorTypes<Fs, Names extends Tuple<keyof Fs>> =
|
export type CtorTypes<Fs, Names extends Tuple<keyof Fs>> =
|
||||||
{ [K in keyof Names]: Fs[keyof Fs & Names[K]] } & any[];
|
{ [K in keyof Names]: Fs[keyof Fs & Names[K]] } & any[];
|
||||||
|
|
||||||
export interface RecordConstructor<L extends Value<T>, Fs, Names extends Tuple<keyof Fs>, T = GenericPointer> {
|
export interface RecordConstructor<L extends Value<T>, Fs, Names extends Tuple<keyof Fs>, T = GenericEmbedded> {
|
||||||
(...fields: CtorTypes<Fs, Names>): Record<L, CtorTypes<Fs, Names>, T>;
|
(...fields: CtorTypes<Fs, Names>): Record<L, CtorTypes<Fs, Names>, T>;
|
||||||
constructorInfo: RecordConstructorInfo<L, T>;
|
constructorInfo: RecordConstructorInfo<L, T>;
|
||||||
isClassOf(v: any): v is Record<L, CtorTypes<Fs, Names>, T>;
|
isClassOf(v: any): v is Record<L, CtorTypes<Fs, Names>, T>;
|
||||||
_: RecordGetters<Fs, Record<L, CtorTypes<Fs, Names>, T>>;
|
_: RecordGetters<Fs, Record<L, CtorTypes<Fs, Names>, T>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface RecordConstructorInfo<L extends Value<T>, T = GenericPointer> {
|
export interface RecordConstructorInfo<L extends Value<T>, T = GenericEmbedded> {
|
||||||
label: L;
|
label: L;
|
||||||
arity: number;
|
arity: number;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export type InferredRecordType<L, FieldsType extends Tuple<any>> =
|
||||||
L extends Value<infer T> ? (FieldsType extends Tuple<Value<T>>
|
L extends Value<infer T> ? (FieldsType extends Tuple<Value<T>>
|
||||||
? Record<L, FieldsType, T>
|
? Record<L, FieldsType, T>
|
||||||
: "TYPE_ERROR_cannotMatchFieldsTypeToLabelType" & [never]) :
|
: "TYPE_ERROR_cannotMatchFieldsTypeToLabelType" & [never]) :
|
||||||
"TYPE_ERROR_cannotInferPointerType" & [never];
|
"TYPE_ERROR_cannotInferEmbeddedType" & [never];
|
||||||
|
|
||||||
export function Record<L, FieldsType extends Tuple<any>>(
|
export function Record<L, FieldsType extends Tuple<any>>(
|
||||||
label: L,
|
label: L,
|
||||||
|
@ -46,7 +46,7 @@ export function Record<L, FieldsType extends Tuple<any>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace Record {
|
export namespace Record {
|
||||||
export function isRecord<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>(x: any): x is Record<L, FieldsType, T> {
|
export function isRecord<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>(x: any): x is Record<L, FieldsType, T> {
|
||||||
return Array.isArray(x) && 'label' in x;
|
return Array.isArray(x) && 'label' in x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,19 +54,19 @@ export namespace Record {
|
||||||
return '<unprintable_preserves_field_value>';
|
return '<unprintable_preserves_field_value>';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function constructorInfo<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>(
|
export function constructorInfo<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>(
|
||||||
r: Record<L, FieldsType, T>): RecordConstructorInfo<L, T>
|
r: Record<L, FieldsType, T>): RecordConstructorInfo<L, T>
|
||||||
{
|
{
|
||||||
return { label: r.label, arity: r.length };
|
return { label: r.label, arity: r.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isClassOf<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>(
|
export function isClassOf<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>(
|
||||||
ci: RecordConstructorInfo<L, T>, v: any): v is Record<L, FieldsType, T>
|
ci: RecordConstructorInfo<L, T>, v: any): v is Record<L, FieldsType, T>
|
||||||
{
|
{
|
||||||
return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length);
|
return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeConstructor<Fs, T = GenericPointer>()
|
export function makeConstructor<Fs, T = GenericEmbedded>()
|
||||||
: (<L extends Value<T>, Names extends Tuple<keyof Fs>>(label: L, fieldNames: Names) =>
|
: (<L extends Value<T>, Names extends Tuple<keyof Fs>>(label: L, fieldNames: Names) =>
|
||||||
RecordConstructor<L, Fs, Names, T>)
|
RecordConstructor<L, Fs, Names, T>)
|
||||||
{
|
{
|
||||||
|
@ -86,7 +86,7 @@ export namespace Record {
|
||||||
|
|
||||||
Array.prototype.asPreservesText = function (): string {
|
Array.prototype.asPreservesText = function (): string {
|
||||||
if ('label' in (this as any)) {
|
if ('label' in (this as any)) {
|
||||||
const r = this as Record<Value, Tuple<Value>, GenericPointer>;
|
const r = this as Record<Value, Tuple<Value>, GenericEmbedded>;
|
||||||
return '<' + r.label.asPreservesText() + (r.length > 0 ? ' ': '') +
|
return '<' + r.label.asPreservesText() + (r.length > 0 ? ' ': '') +
|
||||||
r.map(f => {
|
r.map(f => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,6 +4,8 @@ export * from './codec';
|
||||||
export * from './compound';
|
export * from './compound';
|
||||||
export * from './decoder';
|
export * from './decoder';
|
||||||
export * from './dictionary';
|
export * from './dictionary';
|
||||||
|
export * from './embedded';
|
||||||
|
export * from './embeddedTypes';
|
||||||
export * from './encoder';
|
export * from './encoder';
|
||||||
export * from './flex';
|
export * from './flex';
|
||||||
export * from './float';
|
export * from './float';
|
||||||
|
@ -11,8 +13,6 @@ export * from './fold';
|
||||||
export * from './fromjs';
|
export * from './fromjs';
|
||||||
export * from './is';
|
export * from './is';
|
||||||
export * from './merge';
|
export * from './merge';
|
||||||
export * from './pointer';
|
|
||||||
export * from './pointerTypes';
|
|
||||||
export * from './reader';
|
export * from './reader';
|
||||||
export * from './record';
|
export * from './record';
|
||||||
export * from './strip';
|
export * from './strip';
|
||||||
|
|
|
@ -2,17 +2,17 @@ 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 { GenericPointer } from "./pointer";
|
import type { GenericEmbedded } from "./embedded";
|
||||||
|
|
||||||
export function unannotate<T = GenericPointer>(v: Value<T>): Value<T> {
|
export function unannotate<T = GenericEmbedded>(v: Value<T>): Value<T> {
|
||||||
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function peel<T = GenericPointer>(v: Value<T>): Value<T> {
|
export function peel<T = GenericEmbedded>(v: Value<T>): Value<T> {
|
||||||
return strip(v, 1);
|
return strip(v, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function strip<T = GenericPointer>(
|
export function strip<T = GenericEmbedded>(
|
||||||
v: Value<T>,
|
v: Value<T>,
|
||||||
depth: number = Infinity): Value<T>
|
depth: number = Infinity): Value<T>
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,12 +4,12 @@ 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 { Pointer, GenericPointer } from './pointer';
|
import type { Embedded, GenericEmbedded } from './embedded';
|
||||||
|
|
||||||
export type Value<T = GenericPointer> =
|
export type Value<T = GenericEmbedded> =
|
||||||
| Atom
|
| Atom
|
||||||
| Compound<T>
|
| Compound<T>
|
||||||
| Pointer<T>
|
| Embedded<T>
|
||||||
| Annotated<T>;
|
| Annotated<T>;
|
||||||
export type Atom =
|
export type Atom =
|
||||||
| boolean
|
| boolean
|
||||||
|
@ -19,7 +19,7 @@ export type Atom =
|
||||||
| string
|
| string
|
||||||
| Bytes
|
| Bytes
|
||||||
| symbol;
|
| symbol;
|
||||||
export type Compound<T = GenericPointer> =
|
export type Compound<T = GenericEmbedded> =
|
||||||
| (Array<Value<T>> | [Value<T>]) & { label: Value<T> }
|
| (Array<Value<T>> | [Value<T>]) & { label: Value<T> }
|
||||||
// ^ expanded from definition of Record<> in record.ts,
|
// ^ expanded from definition of Record<> in record.ts,
|
||||||
// because if we use Record<Value<T>, Tuple<Value<T>>, T>,
|
// because if we use Record<Value<T>, Tuple<Value<T>>, T>,
|
||||||
|
|
|
@ -10,15 +10,15 @@ import {
|
||||||
fromJS,
|
fromJS,
|
||||||
Constants,
|
Constants,
|
||||||
Encoder,
|
Encoder,
|
||||||
GenericPointer,
|
GenericEmbedded,
|
||||||
EncoderState,
|
EncoderState,
|
||||||
PointerType,
|
EmbeddedType,
|
||||||
DecoderState,
|
DecoderState,
|
||||||
Decoder,
|
Decoder,
|
||||||
Pointer,
|
Embedded,
|
||||||
embed,
|
embed,
|
||||||
genericPointerTypeDecode,
|
genericEmbeddedTypeDecode,
|
||||||
genericPointerTypeEncode,
|
genericEmbeddedTypeEncode,
|
||||||
} from '../src/index';
|
} from '../src/index';
|
||||||
const { Tag } = Constants;
|
const { Tag } = Constants;
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
|
@ -28,9 +28,9 @@ 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<{}, GenericPointer>()(_discard, []);
|
const Discard = Record.makeConstructor<{}, GenericEmbedded>()(_discard, []);
|
||||||
const Capture = Record.makeConstructor<{pattern: Value<GenericPointer>}, GenericPointer>()(_capture, ['pattern']);
|
const Capture = Record.makeConstructor<{pattern: Value<GenericEmbedded>}, GenericEmbedded>()(_capture, ['pattern']);
|
||||||
const Observe = Record.makeConstructor<{pattern: Value<GenericPointer>}, GenericPointer>()(_observe, ['pattern']);
|
const Observe = Record.makeConstructor<{pattern: Value<GenericEmbedded>}, GenericEmbedded>()(_observe, ['pattern']);
|
||||||
|
|
||||||
describe('record constructors', () => {
|
describe('record constructors', () => {
|
||||||
it('should have constructorInfo', () => {
|
it('should have constructorInfo', () => {
|
||||||
|
@ -46,11 +46,11 @@ describe('record constructors', () => {
|
||||||
describe('RecordConstructorInfo', () => {
|
describe('RecordConstructorInfo', () => {
|
||||||
const C1 = Record.makeConstructor<{x: number, y: number}>()([1], ['x', 'y']);
|
const C1 = Record.makeConstructor<{x: number, y: number}>()([1], ['x', 'y']);
|
||||||
const C2 = Record.makeConstructor<{z: number, w: number}>()([1], ['z', 'w']);
|
const C2 = Record.makeConstructor<{z: number, w: number}>()([1], ['z', 'w']);
|
||||||
it('instance comparison should ignore pointer and fieldname differences', () => {
|
it('instance comparison should ignore embedded and fieldname differences', () => {
|
||||||
expect(C1(9,9)).is(C2(9,9));
|
expect(C1(9,9)).is(C2(9,9));
|
||||||
expect(C1(9,9)).not.is(C2(9,8));
|
expect(C1(9,9)).not.is(C2(9,8));
|
||||||
});
|
});
|
||||||
it('comparison based on pointer equality should not work', () => {
|
it('comparison based on embedded equality should not work', () => {
|
||||||
expect(C1.constructorInfo).not.toBe(C2.constructorInfo);
|
expect(C1.constructorInfo).not.toBe(C2.constructorInfo);
|
||||||
});
|
});
|
||||||
it('comparison based on .equals should work', () => {
|
it('comparison based on .equals should work', () => {
|
||||||
|
@ -87,8 +87,8 @@ describe('reusing buffer space', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('encoding and decoding pointers', () => {
|
describe('encoding and decoding embeddeds', () => {
|
||||||
class LookasidePointerType implements PointerType<object> {
|
class LookasideEmbeddedType implements EmbeddedType<object> {
|
||||||
readonly objects: object[];
|
readonly objects: object[];
|
||||||
|
|
||||||
constructor(objects: object[]) {
|
constructor(objects: object[]) {
|
||||||
|
@ -96,7 +96,7 @@ describe('encoding and decoding pointers', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
decode(d: DecoderState): object {
|
decode(d: DecoderState): object {
|
||||||
return this.fromValue(new Decoder<GenericPointer>(d).next());
|
return this.fromValue(new Decoder<GenericEmbedded>(d).next());
|
||||||
}
|
}
|
||||||
|
|
||||||
encode(e: EncoderState, v: object): void {
|
encode(e: EncoderState, v: object): void {
|
||||||
|
@ -107,9 +107,9 @@ describe('encoding and decoding pointers', () => {
|
||||||
return Object.is(a, b);
|
return Object.is(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fromValue(v: Value<GenericPointer>): object {
|
fromValue(v: Value<GenericEmbedded>): object {
|
||||||
if (typeof v !== 'number' || v < 0 || v >= this.objects.length) {
|
if (typeof v !== 'number' || v < 0 || v >= this.objects.length) {
|
||||||
throw new Error("Unknown pointer target");
|
throw new Error("Unknown embedded target");
|
||||||
}
|
}
|
||||||
return this.objects[v];
|
return this.objects[v];
|
||||||
}
|
}
|
||||||
|
@ -122,54 +122,54 @@ describe('encoding and decoding pointers', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should encode using pointerId when no function has been supplied', () => {
|
it('should encode using embeddedId when no function has been supplied', () => {
|
||||||
const A1 = embed({a: 1});
|
const A1 = embed({a: 1});
|
||||||
const A2 = embed({a: 1});
|
const A2 = embed({a: 1});
|
||||||
const bs1 = canonicalEncode(A1);
|
const bs1 = canonicalEncode(A1);
|
||||||
const bs2 = canonicalEncode(A2);
|
const bs2 = canonicalEncode(A2);
|
||||||
const bs3 = canonicalEncode(A1);
|
const bs3 = canonicalEncode(A1);
|
||||||
expect(bs1.get(0)).toBe(Tag.Pointer);
|
expect(bs1.get(0)).toBe(Tag.Embedded);
|
||||||
expect(bs2.get(0)).toBe(Tag.Pointer);
|
expect(bs2.get(0)).toBe(Tag.Embedded);
|
||||||
expect(bs3.get(0)).toBe(Tag.Pointer);
|
expect(bs3.get(0)).toBe(Tag.Embedded);
|
||||||
// Can't really check the value assigned to the object. But we
|
// Can't really check the value assigned to the object. But we
|
||||||
// can check that it's different to a similar object!
|
// can check that it's different to a similar object!
|
||||||
expect(bs1).not.is(bs2);
|
expect(bs1).not.is(bs2);
|
||||||
expect(bs1).is(bs3);
|
expect(bs1).is(bs3);
|
||||||
});
|
});
|
||||||
it('should refuse to decode pointers when no function has been supplied', () => {
|
it('should refuse to decode embeddeds when no function has been supplied', () => {
|
||||||
expect(() => decode(Bytes.from([Tag.Pointer, Tag.SmallInteger_lo])))
|
expect(() => decode(Bytes.from([Tag.Embedded, Tag.SmallInteger_lo])))
|
||||||
.toThrow("Pointers not permitted at this point in Preserves document");
|
.toThrow("Embeddeds not permitted at this point in Preserves document");
|
||||||
});
|
});
|
||||||
it('should encode properly', () => {
|
it('should encode properly', () => {
|
||||||
const objects: object[] = [];
|
const objects: object[] = [];
|
||||||
const pt = new LookasidePointerType(objects);
|
const pt = new LookasideEmbeddedType(objects);
|
||||||
const A = embed({a: 1});
|
const A = embed({a: 1});
|
||||||
const B = embed({b: 2});
|
const B = embed({b: 2});
|
||||||
expect(encode([A, B], { pointerEncode: pt })).is(
|
expect(encode([A, B], { embeddedEncode: pt })).is(
|
||||||
Bytes.from([Tag.Sequence,
|
Bytes.from([Tag.Sequence,
|
||||||
Tag.Pointer, Tag.SmallInteger_lo,
|
Tag.Embedded, Tag.SmallInteger_lo,
|
||||||
Tag.Pointer, Tag.SmallInteger_lo + 1,
|
Tag.Embedded, Tag.SmallInteger_lo + 1,
|
||||||
Tag.End]));
|
Tag.End]));
|
||||||
expect(objects).toEqual([A.embeddedValue, B.embeddedValue]);
|
expect(objects).toEqual([A.embeddedValue, B.embeddedValue]);
|
||||||
});
|
});
|
||||||
it('should decode properly', () => {
|
it('should decode properly', () => {
|
||||||
const objects: object[] = [];
|
const objects: object[] = [];
|
||||||
const pt = new LookasidePointerType(objects);
|
const pt = new LookasideEmbeddedType(objects);
|
||||||
const X: Pointer<object> = embed({x: 123});
|
const X: Embedded<object> = embed({x: 123});
|
||||||
const Y: Pointer<object> = embed({y: 456});
|
const Y: Embedded<object> = embed({y: 456});
|
||||||
objects.push(X.embeddedValue);
|
objects.push(X.embeddedValue);
|
||||||
objects.push(Y.embeddedValue);
|
objects.push(Y.embeddedValue);
|
||||||
expect(decode(Bytes.from([
|
expect(decode(Bytes.from([
|
||||||
Tag.Sequence,
|
Tag.Sequence,
|
||||||
Tag.Pointer, Tag.SmallInteger_lo,
|
Tag.Embedded, Tag.SmallInteger_lo,
|
||||||
Tag.Pointer, Tag.SmallInteger_lo + 1,
|
Tag.Embedded, Tag.SmallInteger_lo + 1,
|
||||||
Tag.End
|
Tag.End
|
||||||
]), { pointerDecode: pt })).is([X, Y]);
|
]), { embeddedDecode: pt })).is([X, Y]);
|
||||||
});
|
});
|
||||||
it('should store pointers embedded in map keys correctly', () => {
|
it('should store embeddeds embedded in map keys correctly', () => {
|
||||||
const A1a = {a: 1};
|
const A1a = {a: 1};
|
||||||
const A1: Pointer<object> = embed(A1a);
|
const A1: Embedded<object> = embed(A1a);
|
||||||
const A2: Pointer<object> = embed({a: 1});
|
const A2: Embedded<object> = embed({a: 1});
|
||||||
const m = new Dictionary<object, number>();
|
const m = new Dictionary<object, number>();
|
||||||
m.set([A1], 1);
|
m.set([A1], 1);
|
||||||
m.set([A2], 2);
|
m.set([A2], 2);
|
||||||
|
@ -184,61 +184,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, { pointerDecode: genericPointerTypeDecode });
|
const samples = decodeWithAnnotations(samples_bin, { embeddedDecode: genericEmbeddedTypeDecode });
|
||||||
|
|
||||||
const TestCases = Record.makeConstructor<{
|
const TestCases = Record.makeConstructor<{
|
||||||
cases: Dictionary<GenericPointer>
|
cases: Dictionary<GenericEmbedded>
|
||||||
}>()(Symbol.for('TestCases'), ['cases']);
|
}>()(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, { pointerDecode: genericPointerTypeDecode });
|
return decode(bs, { embeddedDecode: genericEmbeddedTypeDecode });
|
||||||
}
|
}
|
||||||
function D(bs: Bytes) {
|
function D(bs: Bytes) {
|
||||||
return decodeWithAnnotations(bs, { pointerDecode: genericPointerTypeDecode });
|
return decodeWithAnnotations(bs, { embeddedDecode: genericEmbeddedTypeDecode });
|
||||||
}
|
}
|
||||||
function E(v: Value<GenericPointer>) {
|
function E(v: Value<GenericEmbedded>) {
|
||||||
return encodeWithAnnotations(v, { pointerEncode: genericPointerTypeEncode });
|
return encodeWithAnnotations(v, { embeddedEncode: genericEmbeddedTypeEncode });
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExpectedValues {
|
interface ExpectedValues {
|
||||||
[testName: string]: ({
|
[testName: string]: ({
|
||||||
value: Value<GenericPointer>;
|
value: Value<GenericEmbedded>;
|
||||||
} | {
|
} | {
|
||||||
forward: Value<GenericPointer>;
|
forward: Value<GenericEmbedded>;
|
||||||
back: Value<GenericPointer>;
|
back: Value<GenericEmbedded>;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const expectedValues: ExpectedValues = {
|
const expectedValues: ExpectedValues = {
|
||||||
annotation1: { forward: annotate<GenericPointer>(9, "abc"),
|
annotation1: { forward: annotate<GenericEmbedded>(9, "abc"),
|
||||||
back: 9 },
|
back: 9 },
|
||||||
annotation2: { forward: annotate<GenericPointer>([[], annotate<GenericPointer>([], "x")],
|
annotation2: { forward: annotate<GenericEmbedded>([[], annotate<GenericEmbedded>([], "x")],
|
||||||
"abc",
|
"abc",
|
||||||
"def"),
|
"def"),
|
||||||
back: [[], []] },
|
back: [[], []] },
|
||||||
annotation3: { forward: annotate<GenericPointer>(5,
|
annotation3: { forward: annotate<GenericEmbedded>(5,
|
||||||
annotate<GenericPointer>(2, 1),
|
annotate<GenericEmbedded>(2, 1),
|
||||||
annotate<GenericPointer>(4, 3)),
|
annotate<GenericEmbedded>(4, 3)),
|
||||||
back: 5 },
|
back: 5 },
|
||||||
annotation5: {
|
annotation5: {
|
||||||
forward: annotate<GenericPointer>(
|
forward: annotate<GenericEmbedded>(
|
||||||
Record<symbol, any>(Symbol.for('R'),
|
Record<symbol, any>(Symbol.for('R'),
|
||||||
[annotate<GenericPointer>(Symbol.for('f'),
|
[annotate<GenericEmbedded>(Symbol.for('f'),
|
||||||
Symbol.for('af'))]),
|
Symbol.for('af'))]),
|
||||||
Symbol.for('ar')),
|
Symbol.for('ar')),
|
||||||
back: Record<Value<GenericPointer>, any>(Symbol.for('R'), [Symbol.for('f')])
|
back: Record<Value<GenericEmbedded>, any>(Symbol.for('R'), [Symbol.for('f')])
|
||||||
},
|
},
|
||||||
annotation6: {
|
annotation6: {
|
||||||
forward: Record<Value<GenericPointer>, any>(
|
forward: Record<Value<GenericEmbedded>, any>(
|
||||||
annotate<GenericPointer>(Symbol.for('R'),
|
annotate<GenericEmbedded>(Symbol.for('R'),
|
||||||
Symbol.for('ar')),
|
Symbol.for('ar')),
|
||||||
[annotate<GenericPointer>(Symbol.for('f'),
|
[annotate<GenericEmbedded>(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<GenericPointer>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
|
forward: annotate<GenericEmbedded>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
|
||||||
back: []
|
back: []
|
||||||
},
|
},
|
||||||
list1: {
|
list1: {
|
||||||
|
@ -258,7 +258,7 @@ describe('common test suite', () => {
|
||||||
function runTestCase(variety: Variety,
|
function runTestCase(variety: Variety,
|
||||||
tName: string,
|
tName: string,
|
||||||
binaryForm: Bytes,
|
binaryForm: Bytes,
|
||||||
annotatedTextForm: Value<GenericPointer>)
|
annotatedTextForm: Value<GenericEmbedded>)
|
||||||
{
|
{
|
||||||
describe(tName, () => {
|
describe(tName, () => {
|
||||||
const textForm = strip(annotatedTextForm);
|
const textForm = strip(annotatedTextForm);
|
||||||
|
@ -287,10 +287,10 @@ describe('common test suite', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const tests = (peel(TestCases._.cases(peel(samples) as TestCases)) as
|
const tests = (peel(TestCases._.cases(peel(samples) as TestCases)) as
|
||||||
Dictionary<GenericPointer>);
|
Dictionary<GenericEmbedded>);
|
||||||
tests.forEach((t0: Value<GenericPointer>, tName0: Value<GenericPointer>) => {
|
tests.forEach((t0: Value<GenericEmbedded>, tName0: Value<GenericEmbedded>) => {
|
||||||
const tName = Symbol.keyFor(strip(tName0) as symbol)!;
|
const tName = Symbol.keyFor(strip(tName0) as symbol)!;
|
||||||
const t = peel(t0) as Record<symbol, any, GenericPointer>;
|
const t = peel(t0) as Record<symbol, any, GenericEmbedded>;
|
||||||
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,4 +1,4 @@
|
||||||
import { Bytes, Decoder, genericPointerType, encode, Reader } from '../src/index';
|
import { Bytes, Decoder, genericEmbeddedType, encode, Reader } from '../src/index';
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
@ -8,21 +8,21 @@ 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, { pointerDecode: genericPointerType, includeAnnotations: false }).next();
|
const s1 = new Reader(samples_pr, { embeddedDecode: genericEmbeddedType, includeAnnotations: false }).next();
|
||||||
const s2 = new Decoder(samples_bin, { pointerDecode: genericPointerType, includeAnnotations: false }).next();
|
const s2 = new Decoder(samples_bin, { embeddedDecode: genericEmbeddedType, includeAnnotations: false }).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, { pointerDecode: genericPointerType, includeAnnotations: true }).next();
|
const s1 = new Reader(samples_pr, { embeddedDecode: genericEmbeddedType, includeAnnotations: true }).next();
|
||||||
const s2 = new Decoder(samples_bin, { pointerDecode: genericPointerType, includeAnnotations: true }).next();
|
const s2 = new Decoder(samples_bin, { embeddedDecode: genericEmbeddedType, includeAnnotations: true }).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, { pointerDecode: genericPointerType, includeAnnotations: true }).next();
|
const s = new Reader(samples_pr, { embeddedDecode: genericEmbeddedType, includeAnnotations: true }).next();
|
||||||
const bs = Bytes.toIO(encode(s, {
|
const bs = Bytes.toIO(encode(s, {
|
||||||
pointerEncode: genericPointerType,
|
embeddedEncode: genericEmbeddedType,
|
||||||
includeAnnotations: true,
|
includeAnnotations: true,
|
||||||
canonical: true,
|
canonical: true,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Single, Double, fromJS, Dictionary, IDENTITY_FOLD, fold, mapPointers, Value, embed } from '../src/index';
|
import { Single, Double, fromJS, Dictionary, IDENTITY_FOLD, fold, mapEmbeddeds, Value, embed } from '../src/index';
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
|
|
||||||
describe('Single', () => {
|
describe('Single', () => {
|
||||||
|
@ -33,7 +33,7 @@ describe('fold', () => {
|
||||||
const w1 = new Date();
|
const w1 = new Date();
|
||||||
const v1 = mkv(w1);
|
const v1 = mkv(w1);
|
||||||
expect(fold(v, IDENTITY_FOLD)).not.is(v1);
|
expect(fold(v, IDENTITY_FOLD)).not.is(v1);
|
||||||
expect(mapPointers(v, _t => embed(w1))).is(v1);
|
expect(mapEmbeddeds(v, _t => embed(w1))).is(v1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@preserves/schema",
|
"name": "@preserves/schema",
|
||||||
"version": "0.7.0",
|
"version": "0.8.0",
|
||||||
"description": "Schema support for Preserves data serialization format",
|
"description": "Schema support for Preserves data serialization format",
|
||||||
"homepage": "https://gitlab.com/preserves/preserves",
|
"homepage": "https://gitlab.com/preserves/preserves",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
"preserves-schemac": "./bin/preserves-schemac.js"
|
"preserves-schemac": "./bin/preserves-schemac.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@preserves/core": "^0.14.0",
|
"@preserves/core": "^0.15.0",
|
||||||
"@types/glob": "^7.1.3",
|
"@types/glob": "^7.1.3",
|
||||||
"@types/minimatch": "^3.0.3",
|
"@types/minimatch": "^3.0.3",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
|
|
|
@ -12,13 +12,13 @@ import { sourceCodeFor } from "./compiler/value";
|
||||||
export function compile(env: M.Environment, schema: M.Schema, options: CompilerOptions = {}): string {
|
export function compile(env: M.Environment, schema: M.Schema, options: CompilerOptions = {}): string {
|
||||||
const mod = new ModuleContext(env, schema, options);
|
const mod = new ModuleContext(env, schema, options);
|
||||||
|
|
||||||
const pointerName = schema.pointer;
|
const embeddedName = schema.embeddedType;
|
||||||
mod.defineType(seq(`export type _ptr = `,
|
mod.defineType(seq(`export type _embedded = `,
|
||||||
renderType(pointerName._variant === 'false'
|
renderType(embeddedName._variant === 'false'
|
||||||
? Type.ref('any')
|
? Type.ref('any')
|
||||||
: typeForDefinition(mod, M.Definition.Alternative(M.Alternative.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(pointerName.value)))))),
|
: typeForDefinition(mod, M.Definition.Alternative(M.Alternative.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(embeddedName.value)))))),
|
||||||
`;`));
|
`;`));
|
||||||
mod.defineType(`export type _val = _.Value<_ptr>;`);
|
mod.defineType(`export type _val = _.Value<_embedded>;`);
|
||||||
|
|
||||||
for (const [name, def] of schema.definitions) {
|
for (const [name, def] of schema.definitions) {
|
||||||
const t = typeForDefinition(mod, def);
|
const t = typeForDefinition(mod, def);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { ANY_TYPE, renderType, Type, variantInitFor } from "./type";
|
||||||
|
|
||||||
export interface CompilerOptions {
|
export interface CompilerOptions {
|
||||||
preservesModule?: string;
|
preservesModule?: string;
|
||||||
defaultPointer?: M.Ref;
|
defaultEmbeddedType?: M.Ref;
|
||||||
warn?(message: string, pos: Position | null): void;
|
warn?(message: string, pos: Position | null): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ export class ModuleContext {
|
||||||
readonly schema: M.Schema;
|
readonly schema: M.Schema;
|
||||||
readonly options: CompilerOptions;
|
readonly options: CompilerOptions;
|
||||||
|
|
||||||
readonly literals = new Dictionary<M._ptr, string>();
|
readonly literals = new Dictionary<M._embedded, string>();
|
||||||
readonly typedefs: Item[] = [];
|
readonly typedefs: Item[] = [];
|
||||||
readonly functiondefs: Item[] = [];
|
readonly functiondefs: Item[] = [];
|
||||||
readonly imports = new KeyedSet<[string, string]>();
|
readonly imports = new KeyedSet<[string, string]>();
|
||||||
|
|
|
@ -134,7 +134,7 @@ function converterFor(
|
||||||
const r = ctx.gentemp(setType(ctx.mod, setPattern));
|
const r = ctx.gentemp(setType(ctx.mod, setPattern));
|
||||||
const v = ctx.gentempname();
|
const v = ctx.gentempname();
|
||||||
return [
|
return [
|
||||||
seq(`if (_.Set.isSet<_ptr>(${src})) `, ctx.block(() => [
|
seq(`if (_.Set.isSet<_embedded>(${src})) `, ctx.block(() => [
|
||||||
seq(`${r} = new _.KeyedSet()`),
|
seq(`${r} = new _.KeyedSet()`),
|
||||||
seq(`for (const ${v} of ${src}) `, ctx.block(() => [
|
seq(`for (const ${v} of ${src}) `, ctx.block(() => [
|
||||||
... converterFor(ctx, M.anonymousSimplePattern(setPattern), v, vv =>
|
... converterFor(ctx, M.anonymousSimplePattern(setPattern), v, vv =>
|
||||||
|
@ -150,7 +150,7 @@ function converterFor(
|
||||||
const v = ctx.gentempname();
|
const v = ctx.gentempname();
|
||||||
const k = ctx.gentempname();
|
const k = ctx.gentempname();
|
||||||
return [
|
return [
|
||||||
seq(`if (_.Dictionary.isDictionary<_ptr>(${src})) `, ctx.block(() => [
|
seq(`if (_.Dictionary.isDictionary<_embedded>(${src})) `, ctx.block(() => [
|
||||||
seq(`${r} = new _.KeyedDictionary()`),
|
seq(`${r} = new _.KeyedDictionary()`),
|
||||||
seq(`for (const [${k}, ${v}] of ${src}) `, ctx.block(() => [
|
seq(`for (const [${k}, ${v}] of ${src}) `, ctx.block(() => [
|
||||||
... converterFor(ctx, M.anonymousSimplePattern(keyPattern), k, kk =>
|
... converterFor(ctx, M.anonymousSimplePattern(keyPattern), k, kk =>
|
||||||
|
@ -205,8 +205,8 @@ export function converterForSimple(
|
||||||
ctx.mod.imports.add([modId, modPath]);
|
ctx.mod.imports.add([modId, modPath]);
|
||||||
return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`];
|
return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`];
|
||||||
});
|
});
|
||||||
case 'pointer':
|
case 'embedded':
|
||||||
return [`${dest} = _.isPointer<_ptr>(${src}) ? ${src}.embeddedValue : void 0`];
|
return [`${dest} = _.isEmbedded<_embedded>(${src}) ? ${src}.embeddedValue : void 0`];
|
||||||
default:
|
default:
|
||||||
((_p: never) => {})(p);
|
((_p: never) => {})(p);
|
||||||
throw new Error("Unreachable");
|
throw new Error("Unreachable");
|
||||||
|
@ -222,7 +222,7 @@ function converterForCompound(
|
||||||
{
|
{
|
||||||
switch (p._variant) {
|
switch (p._variant) {
|
||||||
case 'rec':
|
case 'rec':
|
||||||
return [seq(`if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${src})) `, ctx.block(() =>
|
return [seq(`if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(${src})) `, ctx.block(() =>
|
||||||
converterFor(ctx, p.label, `${src}.label`, () =>
|
converterFor(ctx, p.label, `${src}.label`, () =>
|
||||||
converterFor(ctx, p.fields, src, ks, true))))];
|
converterFor(ctx, p.fields, src, ks, true))))];
|
||||||
case 'tuple':
|
case 'tuple':
|
||||||
|
@ -249,7 +249,7 @@ function converterForCompound(
|
||||||
return ks();
|
return ks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [seq(`if (_.Dictionary.isDictionary<_ptr>(${src})) `, ctx.block(() => loop(0)))];
|
return [seq(`if (_.Dictionary.isDictionary<_embedded>(${src})) `, ctx.block(() => loop(0)))];
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
((_p: never) => {})(p);
|
((_p: never) => {})(p);
|
||||||
|
|
|
@ -72,8 +72,8 @@ export function simpleType(mod: ModuleContext, p: M.SimplePattern): AtomicType {
|
||||||
case 'ByteString': return Type.ref(`_.Bytes`);
|
case 'ByteString': return Type.ref(`_.Bytes`);
|
||||||
case 'Symbol': return Type.ref(`symbol`);
|
case 'Symbol': return Type.ref(`symbol`);
|
||||||
}
|
}
|
||||||
case 'pointer':
|
case 'embedded':
|
||||||
return Type.ref(`_ptr`);
|
return Type.ref(`_embedded`);
|
||||||
case 'lit':
|
case 'lit':
|
||||||
return Type.unit();
|
return Type.unit();
|
||||||
case 'Ref':
|
case 'Ref':
|
||||||
|
|
|
@ -103,8 +103,8 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
|
||||||
}
|
}
|
||||||
case 'lit':
|
case 'lit':
|
||||||
return ctx.mod.literal(p.value);
|
return ctx.mod.literal(p.value);
|
||||||
case 'pointer':
|
case 'embedded':
|
||||||
return `_.embed(${src})`;
|
return `_.embedded(${src})`;
|
||||||
case 'Ref':
|
case 'Ref':
|
||||||
return M.lookup(
|
return M.lookup(
|
||||||
refPosition(p.value), p.value, ctx.mod.env,
|
refPosition(p.value), p.value, ctx.mod.env,
|
||||||
|
@ -167,7 +167,7 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
|
||||||
throw new InsufficientInformationError(
|
throw new InsufficientInformationError(
|
||||||
`C Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`);
|
`C Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`);
|
||||||
}
|
}
|
||||||
return seq(`new _.Set<_ptr>`, parens(
|
return seq(`new _.Set<_embedded>`, parens(
|
||||||
`_.Array.from(${src}.values()).map(v => `,
|
`_.Array.from(${src}.values()).map(v => `,
|
||||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v', t),
|
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v', t),
|
||||||
`)`));
|
`)`));
|
||||||
|
@ -176,14 +176,14 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
|
||||||
throw new InsufficientInformationError(
|
throw new InsufficientInformationError(
|
||||||
`D Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`);
|
`D Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`);
|
||||||
}
|
}
|
||||||
return seq(`new _.Dictionary<_ptr>`, parens(seq(
|
return seq(`new _.Dictionary<_embedded>`, parens(seq(
|
||||||
`_.Array.from(${src}.entries()).map(([k, v]) => `,
|
`_.Array.from(${src}.entries()).map(([k, v]) => `,
|
||||||
brackets(
|
brackets(
|
||||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k', t),
|
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k', t),
|
||||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v', t)),
|
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v', t)),
|
||||||
`)`)));
|
`)`)));
|
||||||
case 'dict':
|
case 'dict':
|
||||||
return seq(`new _.Dictionary<_ptr>`, parens(
|
return seq(`new _.Dictionary<_embedded>`, parens(
|
||||||
brackets(... Array.from(p.entries.entries()).map(([k, n]) =>
|
brackets(... Array.from(p.entries.entries()).map(([k, n]) =>
|
||||||
brackets(
|
brackets(
|
||||||
ctx.mod.literal(k),
|
ctx.mod.literal(k),
|
||||||
|
|
|
@ -74,11 +74,11 @@ export function renderType(t: Type): Item {
|
||||||
case 'ref': return t.typeName;
|
case 'ref': return t.typeName;
|
||||||
case 'set': return seq('_.KeyedSet', anglebrackets(
|
case 'set': return seq('_.KeyedSet', anglebrackets(
|
||||||
renderType(t.type),
|
renderType(t.type),
|
||||||
'_ptr'));
|
'_embedded'));
|
||||||
case 'dictionary': return seq('_.KeyedDictionary', anglebrackets(
|
case 'dictionary': return seq('_.KeyedDictionary', anglebrackets(
|
||||||
renderType(t.key),
|
renderType(t.key),
|
||||||
renderType(t.value),
|
renderType(t.value),
|
||||||
'_ptr'));
|
'_embedded'));
|
||||||
case 'array': return seq('Array', anglebrackets(renderType(t.type)));
|
case 'array': return seq('Array', anglebrackets(renderType(t.type)));
|
||||||
case 'record': return braces(... Array.from(t.fields).map(([nn, tt]) =>
|
case 'record': return braces(... Array.from(t.fields).map(([nn, tt]) =>
|
||||||
keyvalue(nn, renderType(tt))));
|
keyvalue(nn, renderType(tt))));
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Annotated, Bytes, Set, Dictionary, Fold, fold, Record, Tuple, Value, st
|
||||||
import { brackets, Item, parens, seq } from "./block";
|
import { brackets, Item, parens, seq } from "./block";
|
||||||
import * as M from '../meta';
|
import * as M from '../meta';
|
||||||
|
|
||||||
export function sourceCodeFor(v: Value<M._ptr>): Item {
|
export function sourceCodeFor(v: Value<M._embedded>): Item {
|
||||||
return fold(v, {
|
return fold(v, {
|
||||||
boolean(b: boolean): Item { return b.toString(); },
|
boolean(b: boolean): Item { return b.toString(); },
|
||||||
single(f: number): Item { return f.toString(); },
|
single(f: number): Item { return f.toString(); },
|
||||||
|
@ -14,26 +14,26 @@ export function sourceCodeFor(v: Value<M._ptr>): Item {
|
||||||
},
|
},
|
||||||
symbol(s: symbol): Item { return `Symbol.for(${JSON.stringify(s.description!)})`; },
|
symbol(s: symbol): Item { return `Symbol.for(${JSON.stringify(s.description!)})`; },
|
||||||
|
|
||||||
record(r: Record<Value<M._ptr>, Tuple<Value<M._ptr>>, M._ptr>, k: Fold<M._ptr, Item>): Item {
|
record(r: Record<Value<M._embedded>, Tuple<Value<M._embedded>>, M._embedded>, k: Fold<M._embedded, Item>): Item {
|
||||||
return seq(`_.Record<_val, _.Tuple<_val>, _ptr>`, parens(k(r.label), brackets(... r.map(k))));
|
return seq(`_.Record<_val, _.Tuple<_val>, _embedded>`, parens(k(r.label), brackets(... r.map(k))));
|
||||||
},
|
},
|
||||||
array(a: Array<Value<M._ptr>>, k: Fold<M._ptr, Item>): Item {
|
array(a: Array<Value<M._embedded>>, k: Fold<M._embedded, Item>): Item {
|
||||||
return brackets(... a.map(k));
|
return brackets(... a.map(k));
|
||||||
},
|
},
|
||||||
set(s: Set<M._ptr>, k: Fold<M._ptr, Item>): Item {
|
set(s: Set<M._embedded>, k: Fold<M._embedded, Item>): Item {
|
||||||
return seq('new _.Set<_val>', parens(brackets(... Array.from(s).map(k))));
|
return seq('new _.Set<_val>', parens(brackets(... Array.from(s).map(k))));
|
||||||
},
|
},
|
||||||
dictionary(d: Dictionary<M._ptr>, k: Fold<M._ptr, Item>): Item {
|
dictionary(d: Dictionary<M._embedded>, k: Fold<M._embedded, Item>): Item {
|
||||||
return seq('new _.Dictionary<_ptr>', parens(brackets(... Array.from(d).map(([kk,vv]) =>
|
return seq('new _.Dictionary<_embedded>', parens(brackets(... Array.from(d).map(([kk,vv]) =>
|
||||||
brackets(k(kk), k(vv))))));
|
brackets(k(kk), k(vv))))));
|
||||||
},
|
},
|
||||||
|
|
||||||
annotated(a: Annotated<M._ptr>, k: Fold<M._ptr, Item>): Item {
|
annotated(a: Annotated<M._embedded>, k: Fold<M._embedded, Item>): Item {
|
||||||
return seq('_.annotate<_ptr>', parens(k(a.item), ... a.annotations.map(k)));
|
return seq('_.annotate<_embedded>', parens(k(a.item), ... a.annotations.map(k)));
|
||||||
},
|
},
|
||||||
|
|
||||||
pointer(t: M._ptr, _k: Fold<M._ptr, Item>): Item {
|
embedded(t: M._embedded, _k: Fold<M._embedded, Item>): Item {
|
||||||
throw new Error(`Cannot emit source code for construction of pointer ${stringify(t)}`);
|
throw new Error(`Cannot emit source code for construction of embedded ${stringify(t)}`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,11 @@ export const $bundle = Symbol.for("bundle");
|
||||||
export const $definitions = Symbol.for("definitions");
|
export const $definitions = Symbol.for("definitions");
|
||||||
export const $dict = Symbol.for("dict");
|
export const $dict = Symbol.for("dict");
|
||||||
export const $dictof = Symbol.for("dictof");
|
export const $dictof = Symbol.for("dictof");
|
||||||
|
export const $embedded = Symbol.for("embedded");
|
||||||
|
export const $embeddedType = Symbol.for("embeddedType");
|
||||||
export const $lit = Symbol.for("lit");
|
export const $lit = Symbol.for("lit");
|
||||||
export const $named = Symbol.for("named");
|
export const $named = Symbol.for("named");
|
||||||
export const $or = Symbol.for("or");
|
export const $or = Symbol.for("or");
|
||||||
export const $pointer = Symbol.for("pointer");
|
|
||||||
export const $rec = Symbol.for("rec");
|
export const $rec = Symbol.for("rec");
|
||||||
export const $ref = Symbol.for("ref");
|
export const $ref = Symbol.for("ref");
|
||||||
export const $schema = Symbol.for("schema");
|
export const $schema = Symbol.for("schema");
|
||||||
|
@ -28,21 +29,25 @@ export const $tuple$STAR$ = Symbol.for("tuple*");
|
||||||
export const $version = Symbol.for("version");
|
export const $version = Symbol.for("version");
|
||||||
export const __lit6 = false;
|
export const __lit6 = false;
|
||||||
|
|
||||||
export type _ptr = any;
|
export type _embedded = any;
|
||||||
|
|
||||||
export type _val = _.Value<_ptr>;
|
export type _val = _.Value<_embedded>;
|
||||||
|
|
||||||
export type Bundle = {"modules": Modules};
|
export type Bundle = {"modules": Modules};
|
||||||
|
|
||||||
export type Modules = _.KeyedDictionary<ModulePath, Schema, _ptr>;
|
export type Modules = _.KeyedDictionary<ModulePath, Schema, _embedded>;
|
||||||
|
|
||||||
export type Schema = {"version": Version, "pointer": PointerName, "definitions": Definitions};
|
export type Schema = {
|
||||||
|
"version": Version,
|
||||||
|
"embeddedType": EmbeddedTypeName,
|
||||||
|
"definitions": Definitions
|
||||||
|
};
|
||||||
|
|
||||||
export type Version = null;
|
export type Version = null;
|
||||||
|
|
||||||
export type PointerName = ({"_variant": "Ref", "value": Ref} | {"_variant": "false"});
|
export type EmbeddedTypeName = ({"_variant": "Ref", "value": Ref} | {"_variant": "false"});
|
||||||
|
|
||||||
export type Definitions = _.KeyedDictionary<symbol, Definition, _ptr>;
|
export type Definitions = _.KeyedDictionary<symbol, Definition, _embedded>;
|
||||||
|
|
||||||
export type Definition = (
|
export type Definition = (
|
||||||
{
|
{
|
||||||
|
@ -68,7 +73,7 @@ export type Pattern = (
|
||||||
export type SimplePattern = (
|
export type SimplePattern = (
|
||||||
{"_variant": "any"} |
|
{"_variant": "any"} |
|
||||||
{"_variant": "atom", "atomKind": AtomKind} |
|
{"_variant": "atom", "atomKind": AtomKind} |
|
||||||
{"_variant": "pointer"} |
|
{"_variant": "embedded"} |
|
||||||
{"_variant": "lit", "value": _val} |
|
{"_variant": "lit", "value": _val} |
|
||||||
{"_variant": "Ref", "value": Ref}
|
{"_variant": "Ref", "value": Ref}
|
||||||
);
|
);
|
||||||
|
@ -86,7 +91,7 @@ export type CompoundPattern = (
|
||||||
{"_variant": "dict", "entries": DictionaryEntries}
|
{"_variant": "dict", "entries": DictionaryEntries}
|
||||||
);
|
);
|
||||||
|
|
||||||
export type DictionaryEntries = _.KeyedDictionary<_val, NamedSimplePattern, _ptr>;
|
export type DictionaryEntries = _.KeyedDictionary<_val, NamedSimplePattern, _embedded>;
|
||||||
|
|
||||||
export type AtomKind = (
|
export type AtomKind = (
|
||||||
{"_variant": "Boolean"} |
|
{"_variant": "Boolean"} |
|
||||||
|
@ -117,20 +122,22 @@ export type ModulePath = Array<symbol>;
|
||||||
|
|
||||||
export function Bundle(modules: Modules): Bundle {return {"modules": modules};}
|
export function Bundle(modules: Modules): Bundle {return {"modules": modules};}
|
||||||
|
|
||||||
export function Modules(value: _.KeyedDictionary<ModulePath, Schema, _ptr>): Modules {return value;}
|
export function Modules(value: _.KeyedDictionary<ModulePath, Schema, _embedded>): Modules {return value;}
|
||||||
|
|
||||||
export function Schema(
|
export function Schema(
|
||||||
{version, pointer, definitions}: {version: Version, pointer: PointerName, definitions: Definitions}
|
{version, embeddedType, definitions}: {version: Version, embeddedType: EmbeddedTypeName, definitions: Definitions}
|
||||||
): Schema {return {"version": version, "pointer": pointer, "definitions": definitions};}
|
): Schema {
|
||||||
|
return {"version": version, "embeddedType": embeddedType, "definitions": definitions};
|
||||||
|
}
|
||||||
|
|
||||||
export function Version(): Version {return null;}
|
export function Version(): Version {return null;}
|
||||||
|
|
||||||
export namespace PointerName {
|
export namespace EmbeddedTypeName {
|
||||||
export function Ref(value: Ref): PointerName {return {"_variant": "Ref", "value": value};};
|
export function Ref(value: Ref): EmbeddedTypeName {return {"_variant": "Ref", "value": value};};
|
||||||
export function $false(): PointerName {return {"_variant": "false"};};
|
export function $false(): EmbeddedTypeName {return {"_variant": "false"};};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Definitions(value: _.KeyedDictionary<symbol, Definition, _ptr>): Definitions {return value;}
|
export function Definitions(value: _.KeyedDictionary<symbol, Definition, _embedded>): Definitions {return value;}
|
||||||
|
|
||||||
export namespace Definition {
|
export namespace Definition {
|
||||||
export function or(
|
export function or(
|
||||||
|
@ -154,7 +161,7 @@ export namespace Pattern {
|
||||||
export namespace SimplePattern {
|
export namespace SimplePattern {
|
||||||
export function any(): SimplePattern {return {"_variant": "any"};};
|
export function any(): SimplePattern {return {"_variant": "any"};};
|
||||||
export function atom(atomKind: AtomKind): SimplePattern {return {"_variant": "atom", "atomKind": atomKind};};
|
export function atom(atomKind: AtomKind): SimplePattern {return {"_variant": "atom", "atomKind": atomKind};};
|
||||||
export function pointer(): SimplePattern {return {"_variant": "pointer"};};
|
export function embedded(): SimplePattern {return {"_variant": "embedded"};};
|
||||||
export function lit(value: _val): SimplePattern {return {"_variant": "lit", "value": value};};
|
export function lit(value: _val): SimplePattern {return {"_variant": "lit", "value": value};};
|
||||||
export function Ref(value: Ref): SimplePattern {return {"_variant": "Ref", "value": value};};
|
export function Ref(value: Ref): SimplePattern {return {"_variant": "Ref", "value": value};};
|
||||||
}
|
}
|
||||||
|
@ -168,7 +175,7 @@ export namespace CompoundPattern {
|
||||||
export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};};
|
export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DictionaryEntries(value: _.KeyedDictionary<_val, NamedSimplePattern, _ptr>): DictionaryEntries {return value;}
|
export function DictionaryEntries(value: _.KeyedDictionary<_val, NamedSimplePattern, _embedded>): DictionaryEntries {return value;}
|
||||||
|
|
||||||
export namespace AtomKind {
|
export namespace AtomKind {
|
||||||
export function Boolean(): AtomKind {return {"_variant": "Boolean"};};
|
export function Boolean(): AtomKind {return {"_variant": "Boolean"};};
|
||||||
|
@ -204,7 +211,7 @@ export function asBundle(v: _val): Bundle {
|
||||||
|
|
||||||
export function toBundle(v: _val): undefined | Bundle {
|
export function toBundle(v: _val): undefined | Bundle {
|
||||||
let result: undefined | Bundle;
|
let result: undefined | Bundle;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $bundle) ? null : void 0;
|
_tmp0 = _.is(v.label, $bundle) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
|
@ -225,9 +232,9 @@ export function asModules(v: _val): Modules {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toModules(v: _val): undefined | Modules {
|
export function toModules(v: _val): undefined | Modules {
|
||||||
let _tmp0: (_.KeyedDictionary<ModulePath, Schema, _ptr>) | undefined;
|
let _tmp0: (_.KeyedDictionary<ModulePath, Schema, _embedded>) | undefined;
|
||||||
let result: undefined | Modules;
|
let result: undefined | Modules;
|
||||||
if (_.Dictionary.isDictionary<_ptr>(v)) {
|
if (_.Dictionary.isDictionary<_embedded>(v)) {
|
||||||
_tmp0 = new _.KeyedDictionary();
|
_tmp0 = new _.KeyedDictionary();
|
||||||
for (const [_tmp2, _tmp1] of v) {
|
for (const [_tmp2, _tmp1] of v) {
|
||||||
let _tmp3: (ModulePath) | undefined;
|
let _tmp3: (ModulePath) | undefined;
|
||||||
|
@ -246,7 +253,7 @@ export function toModules(v: _val): undefined | Modules {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromModules(_v: Modules): _val {
|
export function fromModules(_v: Modules): _val {
|
||||||
return new _.Dictionary<_ptr>(_.Array.from(_v.entries()).map(([k, v]) => [fromModulePath(k), fromSchema(v)]));
|
return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [fromModulePath(k), fromSchema(v)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asSchema(v: _val): Schema {
|
export function asSchema(v: _val): Schema {
|
||||||
|
@ -257,26 +264,26 @@ export function asSchema(v: _val): Schema {
|
||||||
|
|
||||||
export function toSchema(v: _val): undefined | Schema {
|
export function toSchema(v: _val): undefined | Schema {
|
||||||
let result: undefined | Schema;
|
let result: undefined | Schema;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $schema) ? null : void 0;
|
_tmp0 = _.is(v.label, $schema) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
if (_.Dictionary.isDictionary<_ptr>(v[0])) {
|
if (_.Dictionary.isDictionary<_embedded>(v[0])) {
|
||||||
let _tmp1: (_val) | undefined;
|
let _tmp1: (_val) | undefined;
|
||||||
if ((_tmp1 = v[0].get($version)) !== void 0) {
|
if ((_tmp1 = v[0].get($version)) !== void 0) {
|
||||||
let _tmp2: (Version) | undefined;
|
let _tmp2: (Version) | undefined;
|
||||||
_tmp2 = toVersion(_tmp1);
|
_tmp2 = toVersion(_tmp1);
|
||||||
if (_tmp2 !== void 0) {
|
if (_tmp2 !== void 0) {
|
||||||
let _tmp3: (_val) | undefined;
|
let _tmp3: (_val) | undefined;
|
||||||
if ((_tmp3 = v[0].get($pointer)) !== void 0) {
|
if ((_tmp3 = v[0].get($embeddedType)) !== void 0) {
|
||||||
let _tmp4: (PointerName) | undefined;
|
let _tmp4: (EmbeddedTypeName) | undefined;
|
||||||
_tmp4 = toPointerName(_tmp3);
|
_tmp4 = toEmbeddedTypeName(_tmp3);
|
||||||
if (_tmp4 !== void 0) {
|
if (_tmp4 !== void 0) {
|
||||||
let _tmp5: (_val) | undefined;
|
let _tmp5: (_val) | undefined;
|
||||||
if ((_tmp5 = v[0].get($definitions)) !== void 0) {
|
if ((_tmp5 = v[0].get($definitions)) !== void 0) {
|
||||||
let _tmp6: (Definitions) | undefined;
|
let _tmp6: (Definitions) | undefined;
|
||||||
_tmp6 = toDefinitions(_tmp5);
|
_tmp6 = toDefinitions(_tmp5);
|
||||||
if (_tmp6 !== void 0) {result = {"version": _tmp2, "pointer": _tmp4, "definitions": _tmp6};};
|
if (_tmp6 !== void 0) {result = {"version": _tmp2, "embeddedType": _tmp4, "definitions": _tmp6};};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -292,10 +299,10 @@ export function fromSchema(_v: Schema): _val {
|
||||||
return _.Record(
|
return _.Record(
|
||||||
$schema,
|
$schema,
|
||||||
[
|
[
|
||||||
new _.Dictionary<_ptr>(
|
new _.Dictionary<_embedded>(
|
||||||
[
|
[
|
||||||
[$version, fromVersion(_v["version"])],
|
[$version, fromVersion(_v["version"])],
|
||||||
[$pointer, fromPointerName(_v["pointer"])],
|
[$embeddedType, fromEmbeddedTypeName(_v["embeddedType"])],
|
||||||
[$definitions, fromDefinitions(_v["definitions"])]
|
[$definitions, fromDefinitions(_v["definitions"])]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -319,15 +326,15 @@ export function toVersion(v: _val): undefined | Version {
|
||||||
|
|
||||||
export function fromVersion(_v: Version): _val {return $1;}
|
export function fromVersion(_v: Version): _val {return $1;}
|
||||||
|
|
||||||
export function asPointerName(v: _val): PointerName {
|
export function asEmbeddedTypeName(v: _val): EmbeddedTypeName {
|
||||||
let result = toPointerName(v);
|
let result = toEmbeddedTypeName(v);
|
||||||
if (result === void 0) throw new TypeError(`Invalid PointerName: ${_.stringify(v)}`);
|
if (result === void 0) throw new TypeError(`Invalid EmbeddedTypeName: ${_.stringify(v)}`);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toPointerName(v: _val): undefined | PointerName {
|
export function toEmbeddedTypeName(v: _val): undefined | EmbeddedTypeName {
|
||||||
let _tmp0: (Ref) | undefined;
|
let _tmp0: (Ref) | undefined;
|
||||||
let result: undefined | PointerName;
|
let result: undefined | EmbeddedTypeName;
|
||||||
_tmp0 = toRef(v);
|
_tmp0 = toRef(v);
|
||||||
if (_tmp0 !== void 0) {result = {"_variant": "Ref", "value": _tmp0};};
|
if (_tmp0 !== void 0) {result = {"_variant": "Ref", "value": _tmp0};};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
|
@ -338,7 +345,7 @@ export function toPointerName(v: _val): undefined | PointerName {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromPointerName(_v: PointerName): _val {
|
export function fromEmbeddedTypeName(_v: EmbeddedTypeName): _val {
|
||||||
switch (_v._variant) {case "Ref": {return fromRef(_v.value);}; case "false": {return __lit6;};};
|
switch (_v._variant) {case "Ref": {return fromRef(_v.value);}; case "false": {return __lit6;};};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,9 +356,9 @@ export function asDefinitions(v: _val): Definitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toDefinitions(v: _val): undefined | Definitions {
|
export function toDefinitions(v: _val): undefined | Definitions {
|
||||||
let _tmp0: (_.KeyedDictionary<symbol, Definition, _ptr>) | undefined;
|
let _tmp0: (_.KeyedDictionary<symbol, Definition, _embedded>) | undefined;
|
||||||
let result: undefined | Definitions;
|
let result: undefined | Definitions;
|
||||||
if (_.Dictionary.isDictionary<_ptr>(v)) {
|
if (_.Dictionary.isDictionary<_embedded>(v)) {
|
||||||
_tmp0 = new _.KeyedDictionary();
|
_tmp0 = new _.KeyedDictionary();
|
||||||
for (const [_tmp2, _tmp1] of v) {
|
for (const [_tmp2, _tmp1] of v) {
|
||||||
let _tmp3: (symbol) | undefined;
|
let _tmp3: (symbol) | undefined;
|
||||||
|
@ -370,7 +377,7 @@ export function toDefinitions(v: _val): undefined | Definitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromDefinitions(_v: Definitions): _val {
|
export function fromDefinitions(_v: Definitions): _val {
|
||||||
return new _.Dictionary<_ptr>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromDefinition(v)]));
|
return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromDefinition(v)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asDefinition(v: _val): Definition {
|
export function asDefinition(v: _val): Definition {
|
||||||
|
@ -381,7 +388,7 @@ export function asDefinition(v: _val): Definition {
|
||||||
|
|
||||||
export function toDefinition(v: _val): undefined | Definition {
|
export function toDefinition(v: _val): undefined | Definition {
|
||||||
let result: undefined | Definition;
|
let result: undefined | Definition;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $or) ? null : void 0;
|
_tmp0 = _.is(v.label, $or) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
|
@ -462,7 +469,7 @@ export function asAlternative(v: _val): Alternative {
|
||||||
|
|
||||||
export function toAlternative(v: _val): undefined | Alternative {
|
export function toAlternative(v: _val): undefined | Alternative {
|
||||||
let result: undefined | Alternative;
|
let result: undefined | Alternative;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $and) ? null : void 0;
|
_tmp0 = _.is(v.label, $and) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
|
@ -551,7 +558,7 @@ export function toSimplePattern(v: _val): undefined | SimplePattern {
|
||||||
_tmp0 = _.is(v, $any) ? null : void 0;
|
_tmp0 = _.is(v, $any) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {result = {"_variant": "any"};};
|
if (_tmp0 !== void 0) {result = {"_variant": "any"};};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp1: (null) | undefined;
|
let _tmp1: (null) | undefined;
|
||||||
_tmp1 = _.is(v.label, $atom) ? null : void 0;
|
_tmp1 = _.is(v.label, $atom) ? null : void 0;
|
||||||
if (_tmp1 !== void 0) {
|
if (_tmp1 !== void 0) {
|
||||||
|
@ -561,13 +568,13 @@ export function toSimplePattern(v: _val): undefined | SimplePattern {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp3: (null) | undefined;
|
let _tmp3: (null) | undefined;
|
||||||
_tmp3 = _.is(v.label, $pointer) ? null : void 0;
|
_tmp3 = _.is(v.label, $embedded) ? null : void 0;
|
||||||
if (_tmp3 !== void 0) {result = {"_variant": "pointer"};};
|
if (_tmp3 !== void 0) {result = {"_variant": "embedded"};};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp4: (null) | undefined;
|
let _tmp4: (null) | undefined;
|
||||||
_tmp4 = _.is(v.label, $lit) ? null : void 0;
|
_tmp4 = _.is(v.label, $lit) ? null : void 0;
|
||||||
if (_tmp4 !== void 0) {
|
if (_tmp4 !== void 0) {
|
||||||
|
@ -591,7 +598,7 @@ export function fromSimplePattern(_v: SimplePattern): _val {
|
||||||
switch (_v._variant) {
|
switch (_v._variant) {
|
||||||
case "any": {return $any;};
|
case "any": {return $any;};
|
||||||
case "atom": {return _.Record($atom, [fromAtomKind(_v["atomKind"])]);};
|
case "atom": {return _.Record($atom, [fromAtomKind(_v["atomKind"])]);};
|
||||||
case "pointer": {return _.Record($pointer, []);};
|
case "embedded": {return _.Record($embedded, []);};
|
||||||
case "lit": {return _.Record($lit, [_v["value"]]);};
|
case "lit": {return _.Record($lit, [_v["value"]]);};
|
||||||
case "Ref": {return fromRef(_v.value);};
|
case "Ref": {return fromRef(_v.value);};
|
||||||
};
|
};
|
||||||
|
@ -605,7 +612,7 @@ export function asCompoundPattern(v: _val): CompoundPattern {
|
||||||
|
|
||||||
export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
let result: undefined | CompoundPattern;
|
let result: undefined | CompoundPattern;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $rec) ? null : void 0;
|
_tmp0 = _.is(v.label, $rec) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
|
@ -619,7 +626,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp3: (null) | undefined;
|
let _tmp3: (null) | undefined;
|
||||||
_tmp3 = _.is(v.label, $tuple) ? null : void 0;
|
_tmp3 = _.is(v.label, $tuple) ? null : void 0;
|
||||||
if (_tmp3 !== void 0) {
|
if (_tmp3 !== void 0) {
|
||||||
|
@ -642,7 +649,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp8: (null) | undefined;
|
let _tmp8: (null) | undefined;
|
||||||
_tmp8 = _.is(v.label, $tuple$STAR$) ? null : void 0;
|
_tmp8 = _.is(v.label, $tuple$STAR$) ? null : void 0;
|
||||||
if (_tmp8 !== void 0) {
|
if (_tmp8 !== void 0) {
|
||||||
|
@ -669,7 +676,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp14: (null) | undefined;
|
let _tmp14: (null) | undefined;
|
||||||
_tmp14 = _.is(v.label, $setof) ? null : void 0;
|
_tmp14 = _.is(v.label, $setof) ? null : void 0;
|
||||||
if (_tmp14 !== void 0) {
|
if (_tmp14 !== void 0) {
|
||||||
|
@ -679,7 +686,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp16: (null) | undefined;
|
let _tmp16: (null) | undefined;
|
||||||
_tmp16 = _.is(v.label, $dictof) ? null : void 0;
|
_tmp16 = _.is(v.label, $dictof) ? null : void 0;
|
||||||
if (_tmp16 !== void 0) {
|
if (_tmp16 !== void 0) {
|
||||||
|
@ -693,7 +700,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp19: (null) | undefined;
|
let _tmp19: (null) | undefined;
|
||||||
_tmp19 = _.is(v.label, $dict) ? null : void 0;
|
_tmp19 = _.is(v.label, $dict) ? null : void 0;
|
||||||
if (_tmp19 !== void 0) {
|
if (_tmp19 !== void 0) {
|
||||||
|
@ -740,9 +747,9 @@ export function asDictionaryEntries(v: _val): DictionaryEntries {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
|
export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
|
||||||
let _tmp0: (_.KeyedDictionary<_val, NamedSimplePattern, _ptr>) | undefined;
|
let _tmp0: (_.KeyedDictionary<_val, NamedSimplePattern, _embedded>) | undefined;
|
||||||
let result: undefined | DictionaryEntries;
|
let result: undefined | DictionaryEntries;
|
||||||
if (_.Dictionary.isDictionary<_ptr>(v)) {
|
if (_.Dictionary.isDictionary<_embedded>(v)) {
|
||||||
_tmp0 = new _.KeyedDictionary();
|
_tmp0 = new _.KeyedDictionary();
|
||||||
for (const [_tmp2, _tmp1] of v) {
|
for (const [_tmp2, _tmp1] of v) {
|
||||||
let _tmp3: (_val) | undefined;
|
let _tmp3: (_val) | undefined;
|
||||||
|
@ -761,7 +768,7 @@ export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromDictionaryEntries(_v: DictionaryEntries): _val {
|
export function fromDictionaryEntries(_v: DictionaryEntries): _val {
|
||||||
return new _.Dictionary<_ptr>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromNamedSimplePattern(v)]));
|
return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromNamedSimplePattern(v)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function asAtomKind(v: _val): AtomKind {
|
export function asAtomKind(v: _val): AtomKind {
|
||||||
|
@ -880,7 +887,7 @@ export function asNamedSimplePattern_(v: _val): NamedSimplePattern_ {
|
||||||
|
|
||||||
export function toNamedSimplePattern_(v: _val): undefined | NamedSimplePattern_ {
|
export function toNamedSimplePattern_(v: _val): undefined | NamedSimplePattern_ {
|
||||||
let result: undefined | NamedSimplePattern_;
|
let result: undefined | NamedSimplePattern_;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $named) ? null : void 0;
|
_tmp0 = _.is(v.label, $named) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
|
@ -906,7 +913,7 @@ export function asRef(v: _val): Ref {
|
||||||
|
|
||||||
export function toRef(v: _val): undefined | Ref {
|
export function toRef(v: _val): undefined | Ref {
|
||||||
let result: undefined | Ref;
|
let result: undefined | Ref;
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp0: (null) | undefined;
|
let _tmp0: (null) | undefined;
|
||||||
_tmp0 = _.is(v.label, $ref) ? null : void 0;
|
_tmp0 = _.is(v.label, $ref) ? null : void 0;
|
||||||
if (_tmp0 !== void 0) {
|
if (_tmp0 !== void 0) {
|
||||||
|
|
|
@ -65,8 +65,8 @@ export function parseSchema(toplevelTokens: Array<Input>,
|
||||||
options: ReaderOptions<never> & SchemaReaderOptions): Schema
|
options: ReaderOptions<never> & SchemaReaderOptions): Schema
|
||||||
{
|
{
|
||||||
let version: M.Version | undefined = void 0;
|
let version: M.Version | undefined = void 0;
|
||||||
let pointer: M.PointerName = M.PointerName.$false();
|
let embeddedType: M.EmbeddedTypeName = M.EmbeddedTypeName.$false();
|
||||||
let definitions = new KeyedDictionary<symbol, Definition, M._ptr>();
|
let definitions = new KeyedDictionary<symbol, Definition, M._embedded>();
|
||||||
|
|
||||||
function process(toplevelTokens: Array<Input>): void {
|
function process(toplevelTokens: Array<Input>): void {
|
||||||
const toplevelClauses = splitBy(peel(toplevelTokens) as Array<Input>, M.DOT);
|
const toplevelClauses = splitBy(peel(toplevelTokens) as Array<Input>, M.DOT);
|
||||||
|
@ -86,15 +86,15 @@ export function parseSchema(toplevelTokens: Array<Input>,
|
||||||
definitions.set(name, parseDefinition(name, pos, clause.slice(2)));
|
definitions.set(name, parseDefinition(name, pos, clause.slice(2)));
|
||||||
} else if (clause.length === 2 && is(clause[0], M.$version)) {
|
} else if (clause.length === 2 && is(clause[0], M.$version)) {
|
||||||
version = M.asVersion(peel(clause[1]));
|
version = M.asVersion(peel(clause[1]));
|
||||||
} else if (clause.length === 2 && is(clause[0], M.$pointer)) {
|
} else if (clause.length === 2 && is(clause[0], M.$embeddedType)) {
|
||||||
const pos = position(clause[1]);
|
const pos = position(clause[1]);
|
||||||
const stx = peel(clause[1]);
|
const stx = peel(clause[1]);
|
||||||
if (stx === false) {
|
if (stx === false) {
|
||||||
pointer = M.PointerName.$false();
|
embeddedType = M.EmbeddedTypeName.$false();
|
||||||
} else if (typeof stx === 'symbol') {
|
} else if (typeof stx === 'symbol') {
|
||||||
pointer = M.PointerName.Ref(parseRef(stx.description!, pos));
|
embeddedType = M.EmbeddedTypeName.Ref(parseRef(stx.description!, pos));
|
||||||
} else {
|
} else {
|
||||||
invalidPattern('pointer name specification', stx, pos);
|
invalidPattern('embedded type name specification', stx, pos);
|
||||||
}
|
}
|
||||||
} else if (clause.length === 2 && is(clause[0], M.INCLUDE)) {
|
} else if (clause.length === 2 && is(clause[0], M.INCLUDE)) {
|
||||||
const pos = position(clause[1]);
|
const pos = position(clause[1]);
|
||||||
|
@ -118,7 +118,7 @@ export function parseSchema(toplevelTokens: Array<Input>,
|
||||||
throw new SchemaSyntaxError("Schema: missing version declaration.", null);
|
throw new SchemaSyntaxError("Schema: missing version declaration.", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return M.Schema({ version: M.Version(), pointer, definitions });
|
return M.Schema({ version: M.Version(), embeddedType, definitions });
|
||||||
}
|
}
|
||||||
|
|
||||||
function namedMustBeSimple(p: Position | null): never {
|
function namedMustBeSimple(p: Position | null): never {
|
||||||
|
@ -218,14 +218,14 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
case 'string': return ks(M.SimplePattern.atom(M.AtomKind.String()));
|
case 'string': return ks(M.SimplePattern.atom(M.AtomKind.String()));
|
||||||
case 'bytes': return ks(M.SimplePattern.atom(M.AtomKind.ByteString()));
|
case 'bytes': return ks(M.SimplePattern.atom(M.AtomKind.ByteString()));
|
||||||
case 'symbol': return ks(M.SimplePattern.atom(M.AtomKind.Symbol()));
|
case 'symbol': return ks(M.SimplePattern.atom(M.AtomKind.Symbol()));
|
||||||
case 'ref': return ks(M.SimplePattern.pointer());
|
case 'embedded': return ks(M.SimplePattern.embedded());
|
||||||
default: return ks((str[0] === '=')
|
default: return ks((str[0] === '=')
|
||||||
? M.SimplePattern.lit(Symbol.for(str.slice(1)))
|
? M.SimplePattern.lit(Symbol.for(str.slice(1)))
|
||||||
: M.SimplePattern.Ref(parseRef(str, pos)));
|
: M.SimplePattern.Ref(parseRef(str, pos)));
|
||||||
}
|
}
|
||||||
} else if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) {
|
} else if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
|
||||||
const label = item.label;
|
const label = item.label;
|
||||||
if (Record.isRecord<Input, [], M._ptr>(label)) {
|
if (Record.isRecord<Input, [], M._embedded>(label)) {
|
||||||
if (label.length !== 0) complain();
|
if (label.length !== 0) complain();
|
||||||
switch (label.label) {
|
switch (label.label) {
|
||||||
case M.$lit:
|
case M.$lit:
|
||||||
|
@ -290,9 +290,9 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) {
|
if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
|
||||||
const label = item.label;
|
const label = item.label;
|
||||||
if (Record.isRecord<Input, [], M._ptr>(label)) {
|
if (Record.isRecord<Input, [], M._embedded>(label)) {
|
||||||
if (label.length !== 0) complain();
|
if (label.length !== 0) complain();
|
||||||
switch (label.label) {
|
switch (label.label) {
|
||||||
case M.$rec:
|
case M.$rec:
|
||||||
|
@ -312,7 +312,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(item)) {
|
} else if (Array.isArray(item)) {
|
||||||
return parseArrayLike(item);
|
return parseArrayLike(item);
|
||||||
} else if (Dictionary.isDictionary<M._ptr, Input>(item)) {
|
} else if (Dictionary.isDictionary<M._embedded, Input>(item)) {
|
||||||
if (item.size === 2 && item.has(M.DOTDOTDOT)) {
|
if (item.size === 2 && item.has(M.DOTDOTDOT)) {
|
||||||
const v = item.clone();
|
const v = item.clone();
|
||||||
v.delete(M.DOTDOTDOT);
|
v.delete(M.DOTDOTDOT);
|
||||||
|
@ -320,7 +320,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
return M.CompoundPattern.dictof({ key: walkSimple(kp), value: walkSimple(vp) });
|
return M.CompoundPattern.dictof({ key: walkSimple(kp), value: walkSimple(vp) });
|
||||||
} else {
|
} else {
|
||||||
return M.CompoundPattern.dict(
|
return M.CompoundPattern.dict(
|
||||||
M.DictionaryEntries(item.mapEntries<M.NamedSimplePattern, Input, M._ptr>(
|
M.DictionaryEntries(item.mapEntries<M.NamedSimplePattern, Input, M._embedded>(
|
||||||
([k, vp]) => [
|
([k, vp]) => [
|
||||||
strip(k),
|
strip(k),
|
||||||
_maybeNamed(
|
_maybeNamed(
|
||||||
|
|
|
@ -257,12 +257,12 @@ def annotate(v, *anns):
|
||||||
return v
|
return v
|
||||||
|
|
||||||
class Decoder(Codec):
|
class Decoder(Codec):
|
||||||
def __init__(self, packet=b'', include_annotations=False, decode_pointer=None):
|
def __init__(self, packet=b'', include_annotations=False, decode_embedded=None):
|
||||||
super(Decoder, self).__init__()
|
super(Decoder, self).__init__()
|
||||||
self.packet = packet
|
self.packet = packet
|
||||||
self.index = 0
|
self.index = 0
|
||||||
self.include_annotations = include_annotations
|
self.include_annotations = include_annotations
|
||||||
self.decode_pointer = decode_pointer
|
self.decode_embedded = decode_embedded
|
||||||
|
|
||||||
def extend(self, data):
|
def extend(self, data):
|
||||||
self.packet = self.packet[self.index:] + data
|
self.packet = self.packet[self.index:] + data
|
||||||
|
@ -329,9 +329,9 @@ class Decoder(Codec):
|
||||||
v = self.next()
|
v = self.next()
|
||||||
return self.unshift_annotation(a, v)
|
return self.unshift_annotation(a, v)
|
||||||
if tag == 0x86:
|
if tag == 0x86:
|
||||||
if self.decode_pointer is None:
|
if self.decode_embedded is None:
|
||||||
raise DecodeError('No decode_pointer function supplied')
|
raise DecodeError('No decode_embedded function supplied')
|
||||||
return self.wrap(self.decode_pointer(self.next()))
|
return self.wrap(self.decode_embedded(self.next()))
|
||||||
if tag >= 0x90 and tag <= 0x9f: return self.wrap(tag - (0xa0 if tag > 0x9c else 0x90))
|
if tag >= 0x90 and tag <= 0x9f: return self.wrap(tag - (0xa0 if tag > 0x9c else 0x90))
|
||||||
if tag >= 0xa0 and tag <= 0xaf: return self.wrap(self.nextint(tag - 0xa0 + 1))
|
if tag >= 0xa0 and tag <= 0xaf: return self.wrap(self.nextint(tag - 0xa0 + 1))
|
||||||
if tag == 0xb0: return self.wrap(self.nextint(self.varint()))
|
if tag == 0xb0: return self.wrap(self.nextint(self.varint()))
|
||||||
|
@ -362,10 +362,10 @@ def decode_with_annotations(bs, **kwargs):
|
||||||
return Decoder(packet=bs, include_annotations=True, **kwargs).next()
|
return Decoder(packet=bs, include_annotations=True, **kwargs).next()
|
||||||
|
|
||||||
class Encoder(Codec):
|
class Encoder(Codec):
|
||||||
def __init__(self, encode_pointer=id):
|
def __init__(self, encode_embedded=id):
|
||||||
super(Encoder, self).__init__()
|
super(Encoder, self).__init__()
|
||||||
self.buffer = bytearray()
|
self.buffer = bytearray()
|
||||||
self.encode_pointer = encode_pointer
|
self.encode_embedded = encode_embedded
|
||||||
|
|
||||||
def contents(self):
|
def contents(self):
|
||||||
return bytes(self.buffer)
|
return bytes(self.buffer)
|
||||||
|
@ -435,7 +435,7 @@ class Encoder(Codec):
|
||||||
i = iter(v)
|
i = iter(v)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.buffer.append(0x86)
|
self.buffer.append(0x86)
|
||||||
self.append(self.encode_pointer(v))
|
self.append(self.encode_embedded(v))
|
||||||
return
|
return
|
||||||
self.encodevalues(5, i)
|
self.encodevalues(5, i)
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ class CodecTests(unittest.TestCase):
|
||||||
self._roundtrip((False,) * 100, _buf(0xb5, b'\x80' * 100, 0x84))
|
self._roundtrip((False,) * 100, _buf(0xb5, b'\x80' * 100, 0x84))
|
||||||
self._roundtrip((False,) * 200, _buf(0xb5, b'\x80' * 200, 0x84))
|
self._roundtrip((False,) * 200, _buf(0xb5, b'\x80' * 200, 0x84))
|
||||||
|
|
||||||
def test_pointer_id(self):
|
def test_embedded_id(self):
|
||||||
class A:
|
class A:
|
||||||
def __init__(self, a):
|
def __init__(self, a):
|
||||||
self.a = a
|
self.a = a
|
||||||
|
@ -169,23 +169,23 @@ class CodecTests(unittest.TestCase):
|
||||||
self.assertEqual(_ord(_e(a1)[0]), 0x86)
|
self.assertEqual(_ord(_e(a1)[0]), 0x86)
|
||||||
self.assertEqual(_ord(_e(a2)[0]), 0x86)
|
self.assertEqual(_ord(_e(a2)[0]), 0x86)
|
||||||
|
|
||||||
def test_decode_pointer_absent(self):
|
def test_decode_embedded_absent(self):
|
||||||
with self.assertRaises(DecodeError):
|
with self.assertRaises(DecodeError):
|
||||||
decode(b'\x86\xa0\xff')
|
decode(b'\x86\xa0\xff')
|
||||||
|
|
||||||
def test_encode_pointer(self):
|
def test_encode_embedded(self):
|
||||||
objects = []
|
objects = []
|
||||||
def enc(p):
|
def enc(p):
|
||||||
objects.append(p)
|
objects.append(p)
|
||||||
return len(objects) - 1
|
return len(objects) - 1
|
||||||
self.assertEqual(encode([object(), object()], encode_pointer = enc),
|
self.assertEqual(encode([object(), object()], encode_embedded = enc),
|
||||||
b'\xb5\x86\x90\x86\x91\x84')
|
b'\xb5\x86\x90\x86\x91\x84')
|
||||||
|
|
||||||
def test_decode_pointer(self):
|
def test_decode_embedded(self):
|
||||||
objects = [123, 234]
|
objects = [123, 234]
|
||||||
def dec(v):
|
def dec(v):
|
||||||
return objects[v]
|
return objects[v]
|
||||||
self.assertEqual(decode(b'\xb5\x86\x90\x86\x91\x84', decode_pointer = dec),
|
self.assertEqual(decode(b'\xb5\x86\x90\x86\x91\x84', decode_embedded = dec),
|
||||||
(123, 234))
|
(123, 234))
|
||||||
|
|
||||||
def add_method(d, tName, fn):
|
def add_method(d, tName, fn):
|
||||||
|
@ -254,7 +254,7 @@ def install_exn_test(d, tName, bs, check_proc):
|
||||||
self.fail('did not fail as expected')
|
self.fail('did not fail as expected')
|
||||||
add_method(d, tName, test_exn)
|
add_method(d, tName, test_exn)
|
||||||
|
|
||||||
class Pointer:
|
class Embedded:
|
||||||
def __init__(self, v):
|
def __init__(self, v):
|
||||||
self.v = strip_annotations(v)
|
self.v = strip_annotations(v)
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ class CommonTestSuite(unittest.TestCase):
|
||||||
import os
|
import os
|
||||||
with open(os.path.join(os.path.dirname(__file__),
|
with open(os.path.join(os.path.dirname(__file__),
|
||||||
'../../../tests/samples.bin'), 'rb') as f:
|
'../../../tests/samples.bin'), 'rb') as f:
|
||||||
samples = Decoder(f.read(), include_annotations=True, decode_pointer=Pointer).next()
|
samples = Decoder(f.read(), include_annotations=True, decode_embedded=Embedded).next()
|
||||||
|
|
||||||
TestCases = Record.makeConstructor('TestCases', 'cases')
|
TestCases = Record.makeConstructor('TestCases', 'cases')
|
||||||
|
|
||||||
|
@ -303,13 +303,13 @@ class CommonTestSuite(unittest.TestCase):
|
||||||
raise Exception('Unsupported test kind', t.key)
|
raise Exception('Unsupported test kind', t.key)
|
||||||
|
|
||||||
def DS(self, bs):
|
def DS(self, bs):
|
||||||
return decode(bs, decode_pointer=Pointer)
|
return decode(bs, decode_embedded=Embedded)
|
||||||
|
|
||||||
def D(self, bs):
|
def D(self, bs):
|
||||||
return decode_with_annotations(bs, decode_pointer=Pointer)
|
return decode_with_annotations(bs, decode_embedded=Embedded)
|
||||||
|
|
||||||
def E(self, v):
|
def E(self, v):
|
||||||
return encode(v, encode_pointer=Pointer.value)
|
return encode(v, encode_embedded=Embedded.value)
|
||||||
|
|
||||||
class RecordTests(unittest.TestCase):
|
class RecordTests(unittest.TestCase):
|
||||||
def test_getters(self):
|
def test_getters(self):
|
||||||
|
|
|
@ -5,7 +5,7 @@ except ImportError:
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="preserves",
|
name="preserves",
|
||||||
version="0.5.0",
|
version="0.6.0",
|
||||||
author="Tony Garnock-Jones",
|
author="Tony Garnock-Jones",
|
||||||
author_email="tonyg@leastfixedpoint.com",
|
author_email="tonyg@leastfixedpoint.com",
|
||||||
license="Apache Software License",
|
license="Apache Software License",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
PACKAGENAME=preserves
|
PACKAGENAME=preserves
|
||||||
COLLECTS=preserves
|
COLLECTS=preserves preserves-schema
|
||||||
|
|
||||||
all: setup
|
all: setup
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
(struct record (label fields) #:transparent)
|
(struct record (label fields) #:transparent)
|
||||||
(struct float (value) #:transparent) ;; a marker for single-precision I/O
|
(struct float (value) #:transparent) ;; a marker for single-precision I/O
|
||||||
(struct annotated (annotations item) #:transparent)
|
(struct annotated (annotations item) #:transparent)
|
||||||
(struct pointer (value) #:transparent)
|
(struct embedded (value) #:transparent)
|
||||||
|
|
||||||
;;---------------------------------------------------------------------------
|
;;---------------------------------------------------------------------------
|
||||||
;; Reader
|
;; Reader
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
(match (next)
|
(match (next)
|
||||||
[(annotated as i) (annotated (cons a as) i)]
|
[(annotated as i) (annotated (cons a as) i)]
|
||||||
[i (annotated (list a) i)]))]
|
[i (annotated (list a) i)]))]
|
||||||
[#x86 (pointer (next))]
|
[#x86 (embedded (next))]
|
||||||
[(? (between #x90 #x9C) v) (- v #x90)]
|
[(? (between #x90 #x9C) v) (- v #x90)]
|
||||||
[(? (between #x9D #x9F) v) (- v #xA0)]
|
[(? (between #x9D #x9F) v) (- v #xA0)]
|
||||||
[(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))]
|
[(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))]
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
(for [(a (in-list as))] (write-byte #x85 out-port) (output a))
|
(for [(a (in-list as))] (write-byte #x85 out-port) (output a))
|
||||||
(output v)]
|
(output v)]
|
||||||
|
|
||||||
[(pointer v) (write-byte #x86 out-port) (output v)]
|
[(embedded v) (write-byte #x86 out-port) (output v)]
|
||||||
|
|
||||||
[(? integer?)
|
[(? integer?)
|
||||||
(cond [(<= -3 v -1) (write-byte (+ v #xA0) out-port)]
|
(cond [(<= -3 v -1) (write-byte (+ v #xA0) out-port)]
|
||||||
|
|
|
@ -25,14 +25,14 @@
|
||||||
|
|
||||||
(define (read-preserve [in-port (current-input-port)]
|
(define (read-preserve [in-port (current-input-port)]
|
||||||
#:read-syntax? [read-syntax? #f]
|
#:read-syntax? [read-syntax? #f]
|
||||||
#:decode-pointer [decode-pointer #f]
|
#:decode-embedded [decode-embedded #f]
|
||||||
#:source [source (object-name in-port)])
|
#:source [source (object-name in-port)])
|
||||||
(define b (peek-byte in-port))
|
(define b (peek-byte in-port))
|
||||||
(cond [(eof-object? b) b]
|
(cond [(eof-object? b) b]
|
||||||
[(<= #x80 b #xBF) (read-preserve/binary in-port
|
[(<= #x80 b #xBF) (read-preserve/binary in-port
|
||||||
#:read-syntax? read-syntax?
|
#:read-syntax? read-syntax?
|
||||||
#:decode-pointer decode-pointer)]
|
#:decode-embedded decode-embedded)]
|
||||||
[else (read-preserve/text in-port
|
[else (read-preserve/text in-port
|
||||||
#:read-syntax? read-syntax?
|
#:read-syntax? read-syntax?
|
||||||
#:decode-pointer decode-pointer
|
#:decode-embedded decode-embedded
|
||||||
#:source source)]))
|
#:source source)]))
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
|
|
||||||
(define (default-on-short) (error 'read-preserve/binary "Short Preserves binary"))
|
(define (default-on-short) (error 'read-preserve/binary "Short Preserves binary"))
|
||||||
(define (default-on-fail message . args) (error 'read-preserve/binary (apply format message args)))
|
(define (default-on-fail message . args) (error 'read-preserve/binary (apply format message args)))
|
||||||
(define (default-decode-pointer v)
|
(define (default-decode-embedded v)
|
||||||
(error 'read-preserve/binary "No decode-pointer function supplied"))
|
(error 'read-preserve/binary "No decode-embedded function supplied"))
|
||||||
|
|
||||||
(define (bytes->preserve bs
|
(define (bytes->preserve bs
|
||||||
#:read-syntax? [read-syntax? #f]
|
#:read-syntax? [read-syntax? #f]
|
||||||
#:decode-pointer [decode-pointer #f]
|
#:decode-embedded [decode-embedded #f]
|
||||||
#:on-short [on-short default-on-short]
|
#:on-short [on-short default-on-short]
|
||||||
[on-fail default-on-fail])
|
[on-fail default-on-fail])
|
||||||
(call-with-input-bytes
|
(call-with-input-bytes
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
(lambda (p)
|
(lambda (p)
|
||||||
(match (read-preserve/binary p
|
(match (read-preserve/binary p
|
||||||
#:read-syntax? read-syntax?
|
#:read-syntax? read-syntax?
|
||||||
#:decode-pointer decode-pointer
|
#:decode-embedded decode-embedded
|
||||||
#:on-short on-short
|
#:on-short on-short
|
||||||
on-fail)
|
on-fail)
|
||||||
[(? eof-object?) (on-short)]
|
[(? eof-object?) (on-short)]
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
|
|
||||||
(define (read-preserve/binary [in-port (current-input-port)]
|
(define (read-preserve/binary [in-port (current-input-port)]
|
||||||
#:read-syntax? [read-syntax? #f]
|
#:read-syntax? [read-syntax? #f]
|
||||||
#:decode-pointer [decode-pointer0 #f]
|
#:decode-embedded [decode-embedded0 #f]
|
||||||
#:on-short [on-short default-on-short]
|
#:on-short [on-short default-on-short]
|
||||||
[on-fail default-on-fail])
|
[on-fail default-on-fail])
|
||||||
(define read-annotations? read-syntax?)
|
(define read-annotations? read-syntax?)
|
||||||
(define decode-pointer (or decode-pointer0 default-decode-pointer))
|
(define decode-embedded (or decode-embedded0 default-decode-embedded))
|
||||||
(let/ec return
|
(let/ec return
|
||||||
|
|
||||||
(define (next) (wrap (pos) (next* (next-byte))))
|
(define (next) (wrap (pos) (next* (next-byte))))
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
(if read-annotations?
|
(if read-annotations?
|
||||||
(annotate (next) a)
|
(annotate (next) a)
|
||||||
(next)))]
|
(next)))]
|
||||||
[#x86 (decode-pointer (next))]
|
[#x86 (decode-embedded (next))]
|
||||||
[(? (between #x90 #x9C) v) (- v #x90)]
|
[(? (between #x90 #x9C) v) (- v #x90)]
|
||||||
[(? (between #x9D #x9F) v) (- v #xA0)]
|
[(? (between #x9D #x9F) v) (- v #xA0)]
|
||||||
[(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))]
|
[(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))]
|
||||||
|
|
|
@ -24,18 +24,18 @@
|
||||||
pos
|
pos
|
||||||
#f))
|
#f))
|
||||||
|
|
||||||
(define (default-decode-pointer v)
|
(define (default-decode-embedded v)
|
||||||
(error 'read-preserve/text "No decode-pointer function supplied"))
|
(error 'read-preserve/text "No decode-embedded function supplied"))
|
||||||
|
|
||||||
(define (string->preserve s
|
(define (string->preserve s
|
||||||
#:read-syntax? [read-syntax? #f]
|
#:read-syntax? [read-syntax? #f]
|
||||||
#:decode-pointer [decode-pointer #f]
|
#:decode-embedded [decode-embedded #f]
|
||||||
#:source [source "<string>"])
|
#:source [source "<string>"])
|
||||||
(define p (open-input-string s))
|
(define p (open-input-string s))
|
||||||
(when read-syntax? (port-count-lines! p))
|
(when read-syntax? (port-count-lines! p))
|
||||||
(define v (read-preserve/text p
|
(define v (read-preserve/text p
|
||||||
#:read-syntax? read-syntax?
|
#:read-syntax? read-syntax?
|
||||||
#:decode-pointer decode-pointer
|
#:decode-embedded decode-embedded
|
||||||
#:source source))
|
#:source source))
|
||||||
(when (eof-object? v)
|
(when (eof-object? v)
|
||||||
(parse-error* #:raise-proc raise-read-eof-error p source "Unexpected end of input"))
|
(parse-error* #:raise-proc raise-read-eof-error p source "Unexpected end of input"))
|
||||||
|
@ -53,10 +53,10 @@
|
||||||
|
|
||||||
(define (read-preserve/text [in-port (current-input-port)]
|
(define (read-preserve/text [in-port (current-input-port)]
|
||||||
#:read-syntax? [read-syntax? #f]
|
#:read-syntax? [read-syntax? #f]
|
||||||
#:decode-pointer [decode-pointer0 #f]
|
#:decode-embedded [decode-embedded0 #f]
|
||||||
#:source [source (object-name in-port)])
|
#:source [source (object-name in-port)])
|
||||||
(define read-annotations? read-syntax?)
|
(define read-annotations? read-syntax?)
|
||||||
(define decode-pointer (or decode-pointer0 default-decode-pointer))
|
(define decode-embedded (or decode-embedded0 default-decode-embedded))
|
||||||
|
|
||||||
;;---------------------------------------------------------------------------
|
;;---------------------------------------------------------------------------
|
||||||
;; Core of parser
|
;; Core of parser
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
(apply parse-error (string-append "Embedded binary value: " message) args))
|
(apply parse-error (string-append "Embedded binary value: " message) args))
|
||||||
#:read-syntax? read-syntax?
|
#:read-syntax? read-syntax?
|
||||||
#:on-short (lambda () (parse-error "Incomplete embedded binary value")))]
|
#:on-short (lambda () (parse-error "Incomplete embedded binary value")))]
|
||||||
[#\! (decode-pointer (next))]
|
[#\! (decode-embedded (next))]
|
||||||
[c (parse-error "Invalid # syntax: ~v" c)])]
|
[c (parse-error "Invalid # syntax: ~v" c)])]
|
||||||
|
|
||||||
[#\< (match (read-sequence #\>)
|
[#\< (match (read-sequence #\>)
|
||||||
|
|
|
@ -9,22 +9,22 @@
|
||||||
(require racket/runtime-path)
|
(require racket/runtime-path)
|
||||||
(require syntax/srcloc)
|
(require syntax/srcloc)
|
||||||
|
|
||||||
(struct pointer (value) #:transparent)
|
(struct embedded (value) #:transparent)
|
||||||
|
|
||||||
(define (pointer/no-annotations v)
|
(define (embedded/no-annotations v)
|
||||||
(pointer (strip-annotations v)))
|
(embedded (strip-annotations v)))
|
||||||
|
|
||||||
(define (d bs #:allow-invalid-prefix? [allow-invalid-prefix? #f])
|
(define (d bs #:allow-invalid-prefix? [allow-invalid-prefix? #f])
|
||||||
(for [(i (in-range 1 (- (bytes-length bs) 1)))]
|
(for [(i (in-range 1 (- (bytes-length bs) 1)))]
|
||||||
(define result (bytes->preserve (subbytes bs 0 i)
|
(define result (bytes->preserve (subbytes bs 0 i)
|
||||||
#:decode-pointer pointer/no-annotations
|
#:decode-embedded embedded/no-annotations
|
||||||
#:on-short (lambda () 'short) void))
|
#:on-short (lambda () 'short) void))
|
||||||
(when (and (not (eq? result 'short))
|
(when (and (not (eq? result 'short))
|
||||||
(not (and allow-invalid-prefix? (void? result))))
|
(not (and allow-invalid-prefix? (void? result))))
|
||||||
(error 'd "~a-byte prefix of ~v does not read as short; result: ~v" i bs result)))
|
(error 'd "~a-byte prefix of ~v does not read as short; result: ~v" i bs result)))
|
||||||
(bytes->preserve bs
|
(bytes->preserve bs
|
||||||
#:read-syntax? #t
|
#:read-syntax? #t
|
||||||
#:decode-pointer pointer/no-annotations
|
#:decode-embedded embedded/no-annotations
|
||||||
#:on-short (lambda () 'short)
|
#:on-short (lambda () 'short)
|
||||||
void))
|
void))
|
||||||
|
|
||||||
|
@ -134,28 +134,28 @@
|
||||||
[(asymmetric f b) (values f b #f)] ;; #f because e.g. annotation4 includes annotations
|
[(asymmetric f b) (values f b #f)] ;; #f because e.g. annotation4 includes annotations
|
||||||
[v (values v v #t)]))
|
[v (values v v #t)]))
|
||||||
(check-equal? text-form back loc) ;; expectation 1
|
(check-equal? text-form back loc) ;; expectation 1
|
||||||
(check-equal? (d-strip (preserve->bytes #:encode-pointer pointer-value text-form))
|
(check-equal? (d-strip (preserve->bytes #:encode-embedded embedded-value text-form))
|
||||||
back
|
back
|
||||||
loc) ;; expectation 2
|
loc) ;; expectation 2
|
||||||
(check-equal? (d-strip (preserve->bytes #:encode-pointer pointer-value forward))
|
(check-equal? (d-strip (preserve->bytes #:encode-embedded embedded-value forward))
|
||||||
back
|
back
|
||||||
loc) ;; expectation 3
|
loc) ;; expectation 3
|
||||||
(check-equal? (d-strip binary-form) back loc) ;; expectation 4
|
(check-equal? (d-strip binary-form) back loc) ;; expectation 4
|
||||||
(check-equal? (d binary-form) annotated-text-form loc) ;; expectation 5
|
(check-equal? (d binary-form) annotated-text-form loc) ;; expectation 5
|
||||||
(check-equal? (d (preserve->bytes #:encode-pointer pointer-value annotated-text-form))
|
(check-equal? (d (preserve->bytes #:encode-embedded embedded-value annotated-text-form))
|
||||||
annotated-text-form
|
annotated-text-form
|
||||||
loc) ;; expectation 6
|
loc) ;; expectation 6
|
||||||
(check-equal? (string->preserve #:decode-pointer pointer/no-annotations
|
(check-equal? (string->preserve #:decode-embedded embedded/no-annotations
|
||||||
(preserve->string #:encode-pointer pointer-value text-form))
|
(preserve->string #:encode-embedded embedded-value text-form))
|
||||||
back
|
back
|
||||||
loc) ;; expectation 7
|
loc) ;; expectation 7
|
||||||
(check-equal? (string->preserve #:decode-pointer pointer/no-annotations
|
(check-equal? (string->preserve #:decode-embedded embedded/no-annotations
|
||||||
(preserve->string #:encode-pointer pointer-value forward))
|
(preserve->string #:encode-embedded embedded-value forward))
|
||||||
back
|
back
|
||||||
loc) ;; expectation 8
|
loc) ;; expectation 8
|
||||||
;; similar to 8:
|
;; similar to 8:
|
||||||
(check-equal? (string->preserve #:decode-pointer pointer/no-annotations
|
(check-equal? (string->preserve #:decode-embedded embedded/no-annotations
|
||||||
(preserve->string #:encode-pointer pointer-value
|
(preserve->string #:encode-embedded embedded-value
|
||||||
annotated-text-form)
|
annotated-text-form)
|
||||||
#:read-syntax? #t)
|
#:read-syntax? #t)
|
||||||
annotated-text-form
|
annotated-text-form
|
||||||
|
@ -165,7 +165,7 @@
|
||||||
(and can-execute-nondet-with-canonicalization?)))
|
(and can-execute-nondet-with-canonicalization?)))
|
||||||
;; expectations 9 and 10
|
;; expectations 9 and 10
|
||||||
(check-equal? (preserve->bytes forward
|
(check-equal? (preserve->bytes forward
|
||||||
#:encode-pointer pointer-value
|
#:encode-embedded embedded-value
|
||||||
#:canonicalizing? #t
|
#:canonicalizing? #t
|
||||||
#:write-annotations? #t)
|
#:write-annotations? #t)
|
||||||
binary-form
|
binary-form
|
||||||
|
@ -173,19 +173,19 @@
|
||||||
(unless (memq variety '(decode nondeterministic))
|
(unless (memq variety '(decode nondeterministic))
|
||||||
;; expectation 11
|
;; expectation 11
|
||||||
(check-equal? (preserve->bytes annotated-text-form
|
(check-equal? (preserve->bytes annotated-text-form
|
||||||
#:encode-pointer pointer-value
|
#:encode-embedded embedded-value
|
||||||
#:write-annotations? #t)
|
#:write-annotations? #t)
|
||||||
binary-form
|
binary-form
|
||||||
loc)))
|
loc)))
|
||||||
|
|
||||||
(define-runtime-path tests-path "../../../../../tests")
|
(define-runtime-path tests-path "../../../../../tests")
|
||||||
(let* ((path (build-path tests-path "samples.txt"))
|
(let* ((path (build-path tests-path "samples.pr"))
|
||||||
(testfile (call-with-input-file path
|
(testfile (call-with-input-file path
|
||||||
(lambda (p)
|
(lambda (p)
|
||||||
(port-count-lines! p)
|
(port-count-lines! p)
|
||||||
(read-preserve p
|
(read-preserve p
|
||||||
#:read-syntax? #t
|
#:read-syntax? #t
|
||||||
#:decode-pointer pointer/no-annotations
|
#:decode-embedded embedded/no-annotations
|
||||||
#:source path)))))
|
#:source path)))))
|
||||||
(match-define (peel-annotations `#s(TestCases ,tests)) testfile)
|
(match-define (peel-annotations `#s(TestCases ,tests)) testfile)
|
||||||
(for [((t-name* t*) (in-hash (annotated-item tests)))]
|
(for [((t-name* t*) (in-hash (annotated-item tests)))]
|
||||||
|
|
|
@ -43,21 +43,21 @@
|
||||||
["--no-annotations" "Strip annotations"
|
["--no-annotations" "Strip annotations"
|
||||||
(set! annotations? #f)])
|
(set! annotations? #f)])
|
||||||
|
|
||||||
(struct pointer (value) #:transparent)
|
(struct embedded (value) #:transparent)
|
||||||
|
|
||||||
(let loop ((count count))
|
(let loop ((count count))
|
||||||
(when (positive? count)
|
(when (positive? count)
|
||||||
(define v ((if annotations? values strip-annotations)
|
(define v ((if annotations? values strip-annotations)
|
||||||
(match input-format
|
(match input-format
|
||||||
['any (read-preserve #:read-syntax? #t #:decode-pointer pointer #:source "<stdin>")]
|
['any (read-preserve #:read-syntax? #t #:decode-embedded embedded #:source "<stdin>")]
|
||||||
['text (read-preserve/text #:read-syntax? #t #:decode-pointer pointer #:source "<stdin>")]
|
['text (read-preserve/text #:read-syntax? #t #:decode-embedded embedded #:source "<stdin>")]
|
||||||
['binary (read-preserve/binary #:decode-pointer pointer #:read-syntax? #t)])))
|
['binary (read-preserve/binary #:decode-embedded embedded #:read-syntax? #t)])))
|
||||||
(when (not (eof-object? v))
|
(when (not (eof-object? v))
|
||||||
(void (match output-format
|
(void (match output-format
|
||||||
['text
|
['text
|
||||||
(write-preserve/text v #:indent indent? #:encode-pointer pointer-value)
|
(write-preserve/text v #:indent indent? #:encode-embedded embedded-value)
|
||||||
(newline)]
|
(newline)]
|
||||||
['binary
|
['binary
|
||||||
(write-preserve/binary v #:encode-pointer pointer-value #:write-annotations? #t)]))
|
(write-preserve/binary v #:encode-embedded embedded-value #:write-annotations? #t)]))
|
||||||
(flush-output)
|
(flush-output)
|
||||||
(loop (- count 1))))))
|
(loop (- count 1))))))
|
||||||
|
|
|
@ -16,19 +16,19 @@
|
||||||
|
|
||||||
(define (preserve->bytes v
|
(define (preserve->bytes v
|
||||||
#:canonicalizing? [canonicalizing? #t]
|
#:canonicalizing? [canonicalizing? #t]
|
||||||
#:encode-pointer [encode-pointer #f]
|
#:encode-embedded [encode-embedded #f]
|
||||||
#:write-annotations? [write-annotations? (not canonicalizing?)])
|
#:write-annotations? [write-annotations? (not canonicalizing?)])
|
||||||
(call-with-output-bytes
|
(call-with-output-bytes
|
||||||
(lambda (p) (write-preserve/binary v p
|
(lambda (p) (write-preserve/binary v p
|
||||||
#:canonicalizing? canonicalizing?
|
#:canonicalizing? canonicalizing?
|
||||||
#:encode-pointer encode-pointer
|
#:encode-embedded encode-embedded
|
||||||
#:write-annotations? write-annotations?))))
|
#:write-annotations? write-annotations?))))
|
||||||
|
|
||||||
(define (write-preserve/binary v [out-port (current-output-port)]
|
(define (write-preserve/binary v [out-port (current-output-port)]
|
||||||
#:canonicalizing? [canonicalizing? #t]
|
#:canonicalizing? [canonicalizing? #t]
|
||||||
#:encode-pointer [encode-pointer0 #f]
|
#:encode-embedded [encode-embedded0 #f]
|
||||||
#:write-annotations? [write-annotations? (not canonicalizing?)])
|
#:write-annotations? [write-annotations? (not canonicalizing?)])
|
||||||
(define encode-pointer (or encode-pointer0 object-id))
|
(define encode-embedded (or encode-embedded0 object-id))
|
||||||
|
|
||||||
(define (output-byte b)
|
(define (output-byte b)
|
||||||
(write-byte b out-port))
|
(write-byte b out-port))
|
||||||
|
@ -122,6 +122,6 @@
|
||||||
|
|
||||||
[other
|
[other
|
||||||
(output-byte #x86)
|
(output-byte #x86)
|
||||||
(output (encode-pointer other))]))
|
(output (encode-embedded other))]))
|
||||||
|
|
||||||
(output v))
|
(output v))
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
|
|
||||||
(define (write-preserve/text v0 [o (current-output-port)]
|
(define (write-preserve/text v0 [o (current-output-port)]
|
||||||
#:indent [indent-amount0 #f]
|
#:indent [indent-amount0 #f]
|
||||||
#:encode-pointer [encode-pointer0 #f]
|
#:encode-embedded [encode-embedded0 #f]
|
||||||
#:write-annotations? [write-annotations? #t])
|
#:write-annotations? [write-annotations? #t])
|
||||||
(define encode-pointer (or encode-pointer0 object-id))
|
(define encode-embedded (or encode-embedded0 object-id))
|
||||||
(define indent-amount (match indent-amount0
|
(define indent-amount (match indent-amount0
|
||||||
[#f 0]
|
[#f 0]
|
||||||
[#t 2] ;; a default
|
[#t 2] ;; a default
|
||||||
|
@ -169,16 +169,16 @@
|
||||||
[(? dict?) (write-sequence distance "{" "," "}" write-key-value (dict->list v))]
|
[(? dict?) (write-sequence distance "{" "," "}" write-key-value (dict->list v))]
|
||||||
[other
|
[other
|
||||||
(! "#!")
|
(! "#!")
|
||||||
(write-value distance (encode-pointer other))]))
|
(write-value distance (encode-embedded other))]))
|
||||||
|
|
||||||
(write-value 0 v0))
|
(write-value 0 v0))
|
||||||
|
|
||||||
(define (preserve->string v0
|
(define (preserve->string v0
|
||||||
#:indent [indent-amount #f]
|
#:indent [indent-amount #f]
|
||||||
#:encode-pointer [encode-pointer #f]
|
#:encode-embedded [encode-embedded #f]
|
||||||
#:write-annotations? [write-annotations? #t])
|
#:write-annotations? [write-annotations? #t])
|
||||||
(with-output-to-string
|
(with-output-to-string
|
||||||
(lambda () (write-preserve/text v0
|
(lambda () (write-preserve/text v0
|
||||||
#:indent indent-amount
|
#:indent indent-amount
|
||||||
#:encode-pointer encode-pointer
|
#:encode-embedded encode-embedded
|
||||||
#:write-annotations? write-annotations?))))
|
#:write-annotations? write-annotations?))))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "preserves"
|
name = "preserves"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
|
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Implementation of the Preserves serialization format via serde."
|
description = "Implementation of the Preserves serialization format via serde."
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub enum ExpectedKind {
|
||||||
Set,
|
Set,
|
||||||
Dictionary,
|
Dictionary,
|
||||||
|
|
||||||
Pointer,
|
Embedded,
|
||||||
|
|
||||||
SequenceOrSet, // Because of hacking up serde's data model: see open_sequence_or_set etc.
|
SequenceOrSet, // Because of hacking up serde's data model: see open_sequence_or_set etc.
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub enum Tag {
|
||||||
Double,
|
Double,
|
||||||
End,
|
End,
|
||||||
Annotation,
|
Annotation,
|
||||||
Pointer,
|
Embedded,
|
||||||
SmallInteger(i8),
|
SmallInteger(i8),
|
||||||
MediumInteger(u8),
|
MediumInteger(u8),
|
||||||
SignedInteger,
|
SignedInteger,
|
||||||
|
@ -47,7 +47,7 @@ impl TryFrom<u8> for Tag {
|
||||||
0x83 => Ok(Self::Double),
|
0x83 => Ok(Self::Double),
|
||||||
0x84 => Ok(Self::End),
|
0x84 => Ok(Self::End),
|
||||||
0x85 => Ok(Self::Annotation),
|
0x85 => Ok(Self::Annotation),
|
||||||
0x86 => Ok(Self::Pointer),
|
0x86 => Ok(Self::Embedded),
|
||||||
0x90..=0x9c => Ok(Self::SmallInteger((v - 0x90) as i8)),
|
0x90..=0x9c => Ok(Self::SmallInteger((v - 0x90) as i8)),
|
||||||
0x9d..=0x9f => Ok(Self::SmallInteger((v - 0x90) as i8 - 16)),
|
0x9d..=0x9f => Ok(Self::SmallInteger((v - 0x90) as i8 - 16)),
|
||||||
0xa0..=0xaf => Ok(Self::MediumInteger(v - 0xa0 + 1)),
|
0xa0..=0xaf => Ok(Self::MediumInteger(v - 0xa0 + 1)),
|
||||||
|
@ -73,7 +73,7 @@ impl From<Tag> for u8 {
|
||||||
Tag::Double => 0x83,
|
Tag::Double => 0x83,
|
||||||
Tag::End => 0x84,
|
Tag::End => 0x84,
|
||||||
Tag::Annotation => 0x85,
|
Tag::Annotation => 0x85,
|
||||||
Tag::Pointer => 0x86,
|
Tag::Embedded => 0x86,
|
||||||
Tag::SmallInteger(v) => if v < 0 { (v + 16) as u8 + 0x90 } else { v as u8 + 0x90 },
|
Tag::SmallInteger(v) => if v < 0 { (v + 16) as u8 + 0x90 } else { v as u8 + 0x90 },
|
||||||
Tag::MediumInteger(count) => count - 1 + 0xa0,
|
Tag::MediumInteger(count) => count - 1 + 0xa0,
|
||||||
Tag::SignedInteger => 0xb0,
|
Tag::SignedInteger => 0xb0,
|
||||||
|
|
|
@ -262,7 +262,7 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
|
||||||
self.demand_next(read_annotations)?
|
self.demand_next(read_annotations)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag::Pointer => {
|
Tag::Embedded => {
|
||||||
let v = self.demand_next(read_annotations)?;
|
let v = self.demand_next(read_annotations)?;
|
||||||
Value::Domain(IOValue::from_preserves(v)).wrap()
|
Value::Domain(IOValue::from_preserves(v)).wrap()
|
||||||
}
|
}
|
||||||
|
@ -362,11 +362,11 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
|
||||||
Ok(self.peekend()?)
|
Ok(self.peekend()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_pointer(&mut self) -> ReaderResult<()> {
|
fn open_embedded(&mut self) -> ReaderResult<()> {
|
||||||
self.next_compound(Tag::Pointer, ExpectedKind::Pointer)
|
self.next_compound(Tag::Embedded, ExpectedKind::Embedded)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_pointer(&mut self) -> ReaderResult<()> {
|
fn close_embedded(&mut self) -> ReaderResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ impl Writer for BinaryOrderWriter {
|
||||||
type AnnWriter = PackedWriter<Vec<u8>>;
|
type AnnWriter = PackedWriter<Vec<u8>>;
|
||||||
type SeqWriter = PackedWriter<Vec<u8>>;
|
type SeqWriter = PackedWriter<Vec<u8>>;
|
||||||
type SetWriter = BinaryOrderWriter;
|
type SetWriter = BinaryOrderWriter;
|
||||||
type PointerWriter = PackedWriter<Vec<u8>>;
|
type EmbeddedWriter = PackedWriter<Vec<u8>>;
|
||||||
|
|
||||||
binary_order_writer_method!(mut align(natural_chunksize: u64) -> Result<()>);
|
binary_order_writer_method!(mut align(natural_chunksize: u64) -> Result<()>);
|
||||||
|
|
||||||
|
@ -272,11 +272,11 @@ impl Writer for BinaryOrderWriter {
|
||||||
set.finish(self)
|
set.finish(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_pointer(&mut self) -> Result<Self::PointerWriter> {
|
fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter> {
|
||||||
self.write_tag(Tag::Pointer)?;
|
self.write_tag(Tag::Embedded)?;
|
||||||
Ok(self.pop())
|
Ok(self.pop())
|
||||||
}
|
}
|
||||||
fn end_pointer(&mut self, ptr: Self::PointerWriter) -> Result<()> {
|
fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> Result<()> {
|
||||||
self.push(ptr);
|
self.push(ptr);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ impl<W: std::io::Write> Writer for PackedWriter<W>
|
||||||
type AnnWriter = Self;
|
type AnnWriter = Self;
|
||||||
type SeqWriter = Self;
|
type SeqWriter = Self;
|
||||||
type SetWriter = BinaryOrderWriter;
|
type SetWriter = BinaryOrderWriter;
|
||||||
type PointerWriter = Self;
|
type EmbeddedWriter = Self;
|
||||||
|
|
||||||
fn start_annotations(&mut self) -> Result<Self::AnnWriter> {
|
fn start_annotations(&mut self) -> Result<Self::AnnWriter> {
|
||||||
Ok(self.suspend())
|
Ok(self.suspend())
|
||||||
|
@ -489,12 +489,12 @@ impl<W: std::io::Write> Writer for PackedWriter<W>
|
||||||
set.finish(self)
|
set.finish(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_pointer(&mut self) -> Result<Self::PointerWriter> {
|
fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter> {
|
||||||
self.write_tag(Tag::Pointer)?;
|
self.write_tag(Tag::Embedded)?;
|
||||||
Ok(self.suspend())
|
Ok(self.suspend())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_pointer(&mut self, ann: Self::PointerWriter) -> Result<()> {
|
fn end_embedded(&mut self, ann: Self::EmbeddedWriter) -> Result<()> {
|
||||||
self.resume(ann);
|
self.resume(ann);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ pub trait Reader<'de> {
|
||||||
fn open_set(&mut self) -> ReaderResult<()>;
|
fn open_set(&mut self) -> ReaderResult<()>;
|
||||||
fn open_dictionary(&mut self) -> ReaderResult<()>;
|
fn open_dictionary(&mut self) -> ReaderResult<()>;
|
||||||
fn close_compound(&mut self) -> ReaderResult<bool>;
|
fn close_compound(&mut self) -> ReaderResult<bool>;
|
||||||
fn open_pointer(&mut self) -> ReaderResult<()>;
|
fn open_embedded(&mut self) -> ReaderResult<()>;
|
||||||
fn close_pointer(&mut self) -> ReaderResult<()>;
|
fn close_embedded(&mut self) -> ReaderResult<()>;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -145,12 +145,12 @@ impl<'r, 'de, R: Reader<'de>> Reader<'de> for &'r mut R {
|
||||||
(*self).close_compound()
|
(*self).close_compound()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_pointer(&mut self) -> ReaderResult<()> {
|
fn open_embedded(&mut self) -> ReaderResult<()> {
|
||||||
(*self).open_pointer()
|
(*self).open_embedded()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_pointer(&mut self) -> ReaderResult<()> {
|
fn close_embedded(&mut self) -> ReaderResult<()> {
|
||||||
(*self).close_pointer()
|
(*self).close_embedded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub trait Writer: Sized {
|
||||||
type AnnWriter: AnnotationWriter;
|
type AnnWriter: AnnotationWriter;
|
||||||
type SeqWriter: CompoundWriter;
|
type SeqWriter: CompoundWriter;
|
||||||
type SetWriter: CompoundWriter;
|
type SetWriter: CompoundWriter;
|
||||||
type PointerWriter: Writer;
|
type EmbeddedWriter: Writer;
|
||||||
|
|
||||||
fn align(&mut self, natural_chunksize: u64) -> Result<()>;
|
fn align(&mut self, natural_chunksize: u64) -> Result<()>;
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ pub trait Writer: Sized {
|
||||||
fn start_dictionary(&mut self, entry_count: Option<usize>) -> Result<Self::SetWriter>;
|
fn start_dictionary(&mut self, entry_count: Option<usize>) -> Result<Self::SetWriter>;
|
||||||
fn end_set(&mut self, set: Self::SetWriter) -> Result<()>;
|
fn end_set(&mut self, set: Self::SetWriter) -> Result<()>;
|
||||||
|
|
||||||
fn start_pointer(&mut self) -> Result<Self::PointerWriter>;
|
fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter>;
|
||||||
fn end_pointer(&mut self, ptr: Self::PointerWriter) -> Result<()>;
|
fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> Result<()>;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -133,9 +133,9 @@ pub trait Writer: Sized {
|
||||||
self.end_set(c)
|
self.end_set(c)
|
||||||
}
|
}
|
||||||
Value::Domain(ref d) => {
|
Value::Domain(ref d) => {
|
||||||
let mut c = self.start_pointer()?;
|
let mut c = self.start_embedded()?;
|
||||||
c.write(&d.as_preserves())?;
|
c.write(&d.as_preserves())?;
|
||||||
self.end_pointer(c)
|
self.end_embedded(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn decode_all(bytes: &'_ [u8]) -> Result<Vec<IOValue>, std::io::Error> {
|
||||||
assert_eq!(&PackedWriter::encode(val)?, bin);
|
assert_eq!(&PackedWriter::encode(val)?, bin);
|
||||||
}
|
}
|
||||||
TestCase::NondeterministicTest(ref bin, ref val) => {
|
TestCase::NondeterministicTest(ref bin, ref val) => {
|
||||||
// The test cases in samples.txt are carefully written
|
// The test cases in samples.pr are carefully written
|
||||||
// so that while strictly "nondeterministic", the
|
// so that while strictly "nondeterministic", the
|
||||||
// order of keys in encoded dictionaries follows
|
// order of keys in encoded dictionaries follows
|
||||||
// Preserves canonical order.
|
// Preserves canonical order.
|
||||||
|
|
66
preserves.md
66
preserves.md
|
@ -4,7 +4,7 @@ title: "Preserves: an Expressive Data Language"
|
||||||
---
|
---
|
||||||
|
|
||||||
Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||||
Jan 2021. Version 0.5.0.
|
May 2021. Version 0.6.0.
|
||||||
|
|
||||||
[sexp.txt]: http://people.csail.mit.edu/rivest/Sexp.txt
|
[sexp.txt]: http://people.csail.mit.edu/rivest/Sexp.txt
|
||||||
[spki]: http://world.std.com/~cme/html/spki.html
|
[spki]: http://world.std.com/~cme/html/spki.html
|
||||||
|
@ -36,12 +36,12 @@ definition of the *values* that we want to work with and give them
|
||||||
meaning independent of their syntax.
|
meaning independent of their syntax.
|
||||||
|
|
||||||
Our `Value`s fall into two broad categories: *atomic* and *compound*
|
Our `Value`s fall into two broad categories: *atomic* and *compound*
|
||||||
data. Every `Value` is finite and non-cyclic. References, called
|
data. Every `Value` is finite and non-cyclic. Embedded values, called
|
||||||
`Pointer`s, are a third, special-case category.
|
`Embedded`s, are a third, special-case category.
|
||||||
|
|
||||||
Value = Atom
|
Value = Atom
|
||||||
| Compound
|
| Compound
|
||||||
| Pointer
|
| Embedded
|
||||||
|
|
||||||
Atom = Boolean
|
Atom = Boolean
|
||||||
| Float
|
| Float
|
||||||
|
@ -63,7 +63,7 @@ values of different kinds is essentially arbitrary, but having a total
|
||||||
order is convenient for many tasks, so we define it as
|
order is convenient for many tasks, so we define it as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
(Values) Atom < Compound < Pointer
|
(Values) Atom < Compound < Embedded
|
||||||
|
|
||||||
(Compounds) Record < Sequence < Set < Dictionary
|
(Compounds) Record < Sequence < Set < Dictionary
|
||||||
|
|
||||||
|
@ -160,43 +160,43 @@ pairwise distinct. Instances of `Dictionary` are compared by
|
||||||
lexicographic comparison of the sequences resulting from ordering each
|
lexicographic comparison of the sequences resulting from ordering each
|
||||||
`Dictionary`'s pairs in ascending order by key.
|
`Dictionary`'s pairs in ascending order by key.
|
||||||
|
|
||||||
### Pointers.
|
### Embeddeds.
|
||||||
|
|
||||||
A `Pointer` embeds *domain-specific*, potentially *stateful* or
|
An `Embedded` allows inclusion of *domain-specific*, potentially
|
||||||
*located* data into a `Value`.[^pointer-rationale] `Pointer`s may be
|
*stateful* or *located* data into a `Value`.[^embedded-rationale]
|
||||||
used to denote stateful objects, network services, object
|
`Embedded`s may be used to denote stateful objects, network services,
|
||||||
capabilities, file descriptors, Unix processes, or other
|
object capabilities, file descriptors, Unix processes, or other
|
||||||
possibly-stateful things. Because each `Pointer` is a domain-specific
|
possibly-stateful things. Because each `Embedded` is a domain-specific
|
||||||
datum, comparison of two `Pointer`s is done according to
|
datum, comparison of two `Embedded`s is done according to
|
||||||
domain-specific rules.
|
domain-specific rules.
|
||||||
|
|
||||||
[^pointer-rationale]: **Rationale.** Why include `Pointer`s as a
|
[^embedded-rationale]: **Rationale.** Why include `Embedded`s as a
|
||||||
special class, distinct from, say, a specially-labeled `Record`?
|
special class, distinct from, say, a specially-labeled `Record`?
|
||||||
First, a `Record` can only hold other `Value`s: in order to embed
|
First, a `Record` can only hold other `Value`s: in order to embed
|
||||||
values such as live pointers to Java objects, some means of
|
values such as live pointers to Java objects, some means of
|
||||||
"escaping" from the `Value` data type must be provided. Second,
|
"escaping" from the `Value` data type must be provided. Second,
|
||||||
`Pointer`s are meant to be able to denote stateful entities, for
|
`Embedded`s are meant to be able to denote stateful entities, for
|
||||||
which comparison by address is appropriate; however, we do not
|
which comparison by address is appropriate; however, we do not
|
||||||
wish to place restrictions on the *nature* of these entities: if
|
wish to place restrictions on the *nature* of these entities: if
|
||||||
we had used `Record`s instead of distinct `Pointer`s, users would
|
we had used `Record`s instead of distinct `Embedded`s, users would
|
||||||
have to invent an encoding of domain data into `Record`s that
|
have to invent an encoding of domain data into `Record`s that
|
||||||
reflected domain ordering into `Value` ordering. This is often
|
reflected domain ordering into `Value` ordering. This is often
|
||||||
difficult and may not always be possible. Finally, because
|
difficult and may not always be possible. Finally, because
|
||||||
`Pointer`s are intended to be able to represent network and memory
|
`Embedded`s are intended to be able to represent network and
|
||||||
*locations*, they must be able to be rewritten at network and
|
memory *locations*, they must be able to be rewritten at network
|
||||||
process boundaries. Having a distinct class allows generic
|
and process boundaries. Having a distinct class allows generic
|
||||||
`Pointer` rewriting without the quotation-related complications of
|
`Embedded` rewriting without the quotation-related complications
|
||||||
encoding references as, say, `Record`s.
|
of encoding references as, say, `Record`s.
|
||||||
|
|
||||||
*Examples.* In a Java or Python implementation, a `Pointer` may denote
|
*Examples.* In a Java or Python implementation, an `Embedded` may
|
||||||
a reference to a Java or Python object; comparison would be done via
|
denote a reference to a Java or Python object; comparison would be
|
||||||
the language's own rules for equivalence and ordering. In a Unix
|
done via the language's own rules for equivalence and ordering. In a
|
||||||
application, a `Pointer` may denote an open file descriptor or a
|
Unix application, an `Embedded` may denote an open file descriptor or
|
||||||
process ID. In an HTTP-based application, each `Pointer` might be a
|
a process ID. In an HTTP-based application, each `Embedded` might be a
|
||||||
URL, compared according to
|
URL, compared according to
|
||||||
[RFC 6943](https://tools.ietf.org/html/rfc6943#section-3.3). When a
|
[RFC 6943](https://tools.ietf.org/html/rfc6943#section-3.3). When a
|
||||||
`Value` is serialized for storage or transfer, embedded `Pointer`s
|
`Value` is serialized for storage or transfer, `Embedded`s will
|
||||||
will usually be represented as ordinary `Value`s, in which case the
|
usually be represented as ordinary `Value`s, in which case the
|
||||||
ordinary rules for comparing `Value`s will apply.
|
ordinary rules for comparing `Value`s will apply.
|
||||||
|
|
||||||
## Textual Syntax
|
## Textual Syntax
|
||||||
|
@ -241,7 +241,7 @@ Standalone documents may have trailing whitespace.
|
||||||
|
|
||||||
Any `Value` may be preceded by whitespace.
|
Any `Value` may be preceded by whitespace.
|
||||||
|
|
||||||
Value = ws (Record / Collection / Atom / Pointer / Compact)
|
Value = ws (Record / Collection / Atom / Embedded / Compact)
|
||||||
Collection = Sequence / Dictionary / Set
|
Collection = Sequence / Dictionary / Set
|
||||||
Atom = Boolean / Float / Double / SignedInteger /
|
Atom = Boolean / Float / Double / SignedInteger /
|
||||||
String / ByteString / Symbol
|
String / ByteString / Symbol
|
||||||
|
@ -401,10 +401,10 @@ double quote mark.
|
||||||
definition of “token representation”, and with the
|
definition of “token representation”, and with the
|
||||||
[R6RS definition of identifiers](http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-7.html#node_sec_4.2.4).
|
[R6RS definition of identifiers](http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-7.html#node_sec_4.2.4).
|
||||||
|
|
||||||
A `Pointer` is written as a `Value` chosen to represent the denoted
|
An `Embedded` is written as a `Value` chosen to represent the denoted
|
||||||
object, prefixed with `#!`.
|
object, prefixed with `#!`.
|
||||||
|
|
||||||
Pointer = "#!" Value
|
Embedded = "#!" Value
|
||||||
|
|
||||||
Finally, any `Value` may be represented by escaping from the textual
|
Finally, any `Value` may be represented by escaping from the textual
|
||||||
syntax to the [compact binary syntax](#compact-binary-syntax) by
|
syntax to the [compact binary syntax](#compact-binary-syntax) by
|
||||||
|
@ -621,9 +621,9 @@ contained within the `Value` unmodified.
|
||||||
The functions `binary32(F)` and `binary64(D)` yield big-endian 4- and
|
The functions `binary32(F)` and `binary64(D)` yield big-endian 4- and
|
||||||
8-byte IEEE 754 binary representations of `F` and `D`, respectively.
|
8-byte IEEE 754 binary representations of `F` and `D`, respectively.
|
||||||
|
|
||||||
### Pointers.
|
### Embeddeds.
|
||||||
|
|
||||||
The `Repr` of a `Pointer` is the `Repr` of a `Value` chosen to
|
The `Repr` of an `Embedded` is the `Repr` of a `Value` chosen to
|
||||||
represent the denoted object, prefixed with `[0x86]`.
|
represent the denoted object, prefixed with `[0x86]`.
|
||||||
|
|
||||||
«#!V» = [0x86] ++ «V»
|
«#!V» = [0x86] ++ «V»
|
||||||
|
@ -855,7 +855,7 @@ a binary-syntax document; otherwise, it should be interpreted as text.
|
||||||
83 - Double
|
83 - Double
|
||||||
84 - End marker
|
84 - End marker
|
||||||
85 - Annotation
|
85 - Annotation
|
||||||
86 - Pointer
|
86 - Embedded
|
||||||
(8x) RESERVED 87-8F
|
(8x) RESERVED 87-8F
|
||||||
|
|
||||||
9x - Small integers 0..12,-3..-1
|
9x - Small integers 0..12,-3..-1
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
´³schema·³pointer€³version‘³definitions·³Ref´³rec´³lit³ref„´³tupleµ´³named³module´³refµ„³
|
´³schema·³version‘³definitions·³Ref´³rec´³lit³ref„´³tupleµ´³named³module´³refµ„³
|
||||||
ModulePath„„´³named³name´³atom³Symbol„„„„„³Bundle´³rec´³lit³bundle„´³tupleµ´³named³modules´³refµ„³Modules„„„„„³Schema´³rec´³lit³schema„´³tupleµ´³dict·³pointer´³refµ„³PointerName„³version´³refµ„³Version„³definitions´³refµ„³Definitions„„„„„„³Modules´³dictof´³refµ„³
|
ModulePath„„´³named³name´³atom³Symbol„„„„„³Bundle´³rec´³lit³bundle„´³tupleµ´³named³modules´³refµ„³Modules„„„„„³Schema´³rec´³lit³schema„´³tupleµ´³dict·³version´³refµ„³Version„³definitions´³refµ„³Definitions„³embeddedType´³refµ„³EmbeddedTypeName„„„„„„³Modules´³dictof´³refµ„³
|
||||||
ModulePath„´³refµ„³Schema„„³Pattern´³orµµ±
SimplePattern´³refµ„³
SimplePattern„„µ±CompoundPattern´³refµ„³CompoundPattern„„„„³Version´³lit‘„³AtomKind´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ±
SignedInteger´³lit³
SignedInteger„„µ±String´³lit³String„„µ±
|
ModulePath„´³refµ„³Schema„„³Pattern´³orµµ±
SimplePattern´³refµ„³
SimplePattern„„µ±CompoundPattern´³refµ„³CompoundPattern„„„„³Version´³lit‘„³AtomKind´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ±
SignedInteger´³lit³
SignedInteger„„µ±String´³lit³String„„µ±
|
||||||
ByteString´³lit³
|
ByteString´³lit³
|
||||||
ByteString„„µ±Symbol´³lit³Symbol„„„„³
|
ByteString„„µ±Symbol´³lit³Symbol„„„„³
|
||||||
Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³NamedAlternative„„„´³named³patterns´³refµ„³NamedAlternative„„„„„„„µ±Alternative´³refµ„³Alternative„„„„³
|
Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³NamedAlternative„„„´³named³patterns´³refµ„³NamedAlternative„„„„„„„µ±Alternative´³refµ„³Alternative„„„„³
|
||||||
ModulePath´³tuple*µ„´³atom³Symbol„„³Alternative´³orµµ±and´³rec´³lit³and„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³NamedPattern„„„´³named³patterns´³refµ„³NamedPattern„„„„„„„µ±Pattern´³refµ„³Pattern„„„„³Definitions´³dictof´³atom³Symbol„´³refµ„³
|
ModulePath´³tuple*µ„´³atom³Symbol„„³Alternative´³orµµ±and´³rec´³lit³and„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³NamedPattern„„„´³named³patterns´³refµ„³NamedPattern„„„„„„„µ±Pattern´³refµ„³Pattern„„„„³Definitions´³dictof´³atom³Symbol„´³refµ„³
|
||||||
Definition„„³PointerName´³orµµ±Ref´³refµ„³Ref„„µ±false´³lit€„„„„³NamedPattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³Pattern„„„„³
SimplePattern´³orµµ±any´³lit³any„„µ±atom´³rec´³lit³atom„´³tupleµ´³named³atomKind´³refµ„³AtomKind„„„„„„µ±pointer´³rec´³lit³pointer„´³tupleµ„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„„µ±Ref´³refµ„³Ref„„„„³CompoundPattern´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label´³refµ„³NamedPattern„„´³named³fields´³refµ„³NamedPattern„„„„„„µ±tuple´³rec´³lit³tuple„´³tupleµ´³tuple*µ„´³named³patterns´³refµ„³NamedPattern„„„„„„„µ±tuple*´³rec´³lit³tuple*„´³tupleµ´³tuple*µ„´³named³fixed´³refµ„³NamedPattern„„„´³named³variable´³refµ„³NamedSimplePattern„„„„„„µ±setof´³rec´³lit³setof„´³tupleµ´³named³pattern´³refµ„³
SimplePattern„„„„„„µ±dictof´³rec´³lit³dictof„´³tupleµ´³named³key´³refµ„³
SimplePattern„„´³named³value´³refµ„³
SimplePattern„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³refµ„³DictionaryEntries„„„„„„„„³NamedAlternative´³tupleµ´³named³variantLabel´³atom³String„„´³named³alternative´³refµ„³Alternative„„„„³DictionaryEntries´³dictof³any´³refµ„³NamedSimplePattern„„³NamedSimplePattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³
SimplePattern„„„„³NamedSimplePattern_´³rec´³lit³named„´³tupleµ´³named³name´³atom³Symbol„„´³named³pattern´³refµ„³
SimplePattern„„„„„„„„
|
Definition„„³NamedPattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³Pattern„„„„³
SimplePattern´³orµµ±any´³lit³any„„µ±atom´³rec´³lit³atom„´³tupleµ´³named³atomKind´³refµ„³AtomKind„„„„„„µ±embedded´³rec´³lit³embedded„´³tupleµ„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„„µ±Ref´³refµ„³Ref„„„„³CompoundPattern´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label´³refµ„³NamedPattern„„´³named³fields´³refµ„³NamedPattern„„„„„„µ±tuple´³rec´³lit³tuple„´³tupleµ´³tuple*µ„´³named³patterns´³refµ„³NamedPattern„„„„„„„µ±tuple*´³rec´³lit³tuple*„´³tupleµ´³tuple*µ„´³named³fixed´³refµ„³NamedPattern„„„´³named³variable´³refµ„³NamedSimplePattern„„„„„„µ±setof´³rec´³lit³setof„´³tupleµ´³named³pattern´³refµ„³
SimplePattern„„„„„„µ±dictof´³rec´³lit³dictof„´³tupleµ´³named³key´³refµ„³
SimplePattern„„´³named³value´³refµ„³
SimplePattern„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³refµ„³DictionaryEntries„„„„„„„„³EmbeddedTypeName´³orµµ±Ref´³refµ„³Ref„„µ±false´³lit€„„„„³NamedAlternative´³tupleµ´³named³variantLabel´³atom³String„„´³named³alternative´³refµ„³Alternative„„„„³DictionaryEntries´³dictof³any´³refµ„³NamedSimplePattern„„³NamedSimplePattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³
SimplePattern„„„„³NamedSimplePattern_´³rec´³lit³named„´³tupleµ´³named³name´³atom³Symbol„„´³named³pattern´³refµ„³
SimplePattern„„„„„„³embeddedType€„„
|
|
@ -1,5 +1,8 @@
|
||||||
@<EmacsMode "-*- preserves -*-">
|
@<EmacsMode "-*- preserves -*-">
|
||||||
|
|
||||||
|
; TODO: some kind of constants
|
||||||
|
; TODO: rename "version" to "schema-version" ?
|
||||||
|
|
||||||
version 1 .
|
version 1 .
|
||||||
|
|
||||||
Bundle = <bundle @modules Modules>.
|
Bundle = <bundle @modules Modules>.
|
||||||
|
@ -7,14 +10,14 @@ Modules = { ModulePath: Schema ...:... }.
|
||||||
|
|
||||||
Schema = <schema {
|
Schema = <schema {
|
||||||
version: Version
|
version: Version
|
||||||
pointer: PointerName
|
embeddedType: EmbeddedTypeName
|
||||||
definitions: Definitions
|
definitions: Definitions
|
||||||
}>.
|
}>.
|
||||||
|
|
||||||
; version 1 .
|
; version 1 .
|
||||||
Version = 1 .
|
Version = 1 .
|
||||||
|
|
||||||
PointerName = Ref / #f.
|
EmbeddedTypeName = Ref / #f.
|
||||||
|
|
||||||
Definitions = { symbol: Definition ...:... }.
|
Definitions = { symbol: Definition ...:... }.
|
||||||
|
|
||||||
|
@ -37,8 +40,8 @@ SimplePattern =
|
||||||
; special builtins: bool, float, double, int, string, bytes, symbol
|
; special builtins: bool, float, double, int, string, bytes, symbol
|
||||||
/ <atom @atomKind AtomKind>
|
/ <atom @atomKind AtomKind>
|
||||||
|
|
||||||
; matches a pointer in the input: ref
|
; matches an embedded value in the input: embedded
|
||||||
/ <pointer>
|
/ <embedded>
|
||||||
|
|
||||||
; =symbol, <<lit> any>, or plain non-symbol atom
|
; =symbol, <<lit> any>, or plain non-symbol atom
|
||||||
/ <lit @value any>
|
/ <lit @value any>
|
||||||
|
|
Binary file not shown.
|
@ -112,9 +112,9 @@
|
||||||
list9: @"Unexpected close bracket" <ParseError "]">
|
list9: @"Unexpected close bracket" <ParseError "]">
|
||||||
list10: @"Missing end byte" <DecodeShort #x"b58080">
|
list10: @"Missing end byte" <DecodeShort #x"b58080">
|
||||||
noinput0: @"No input at all" <DecodeEOF #x"">
|
noinput0: @"No input at all" <DecodeEOF #x"">
|
||||||
pointer0: <Test #x"8690" #!0>
|
embed0: <Test #x"8690" #!0>
|
||||||
pointer1: <Test #x"868690" #!#!0>
|
embed1: <Test #x"868690" #!#!0>
|
||||||
pointer2: <Test #x"b5869086b10568656c6c6f84" [#!0 #!"hello"]>
|
embed2: <Test #x"b5869086b10568656c6c6f84" [#!0 #!"hello"]>
|
||||||
record1: <Test #x"b4 b30763617074757265 b4 b30764697363617264 84 84" <capture <discard>>>
|
record1: <Test #x"b4 b30763617074757265 b4 b30764697363617264 84 84" <capture <discard>>>
|
||||||
record2: <Test #x"b4 b3076f627365727665 b4 b305737065616b b4 b30764697363617264 84 b4 b30763617074757265 b4 b30764697363617264 84 84 84 84" <observe <speak <discard>, <capture <discard>>>>>
|
record2: <Test #x"b4 b3076f627365727665 b4 b305737065616b b4 b30764697363617264 84 b4 b30763617074757265 b4 b30764697363617264 84 84 84 84" <observe <speak <discard>, <capture <discard>>>>>
|
||||||
record3: <Test #x"b4 b5 b3067469746c6564 b306706572736f6e 92 b3057468696e67 91 84 a065 b109426c61636b77656c6c b4 b30464617465 a1071d 92 93 84 b1024472 84" <[titled person 2 thing 1] 101 "Blackwell" <date 1821 2 3> "Dr">>
|
record3: <Test #x"b4 b5 b3067469746c6564 b306706572736f6e 92 b3057468696e67 91 84 a065 b109426c61636b77656c6c b4 b30464617465 a1071d 92 93 84 b1024472 84" <[titled person 2 thing 1] 101 "Blackwell" <date 1821 2 3> "Dr">>
|
||||||
|
|
Loading…
Reference in New Issue