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