Browse Source

The Great Renaming: Pointer -> Embedded

main javascript-@preserves/core@0.15.0
Tony Garnock-Jones 4 months ago
parent
commit
e4a2503899
  1. 2
      canonical-binary.md
  2. 2
      implementations/javascript/packages/core/package.json
  3. 10
      implementations/javascript/packages/core/src/annotated.ts
  4. 4
      implementations/javascript/packages/core/src/bytes.ts
  5. 4
      implementations/javascript/packages/core/src/compound.ts
  6. 2
      implementations/javascript/packages/core/src/constants.ts
  7. 50
      implementations/javascript/packages/core/src/decoder.ts
  8. 22
      implementations/javascript/packages/core/src/dictionary.ts
  9. 22
      implementations/javascript/packages/core/src/embedded.ts
  10. 50
      implementations/javascript/packages/core/src/embeddedTypes.ts
  11. 50
      implementations/javascript/packages/core/src/encoder.ts
  12. 6
      implementations/javascript/packages/core/src/float.ts
  13. 14
      implementations/javascript/packages/core/src/fold.ts
  14. 8
      implementations/javascript/packages/core/src/fromjs.ts
  15. 4
      implementations/javascript/packages/core/src/is.ts
  16. 10
      implementations/javascript/packages/core/src/merge.ts
  17. 50
      implementations/javascript/packages/core/src/pointerTypes.ts
  18. 34
      implementations/javascript/packages/core/src/reader.ts
  19. 20
      implementations/javascript/packages/core/src/record.ts
  20. 4
      implementations/javascript/packages/core/src/runtime.ts
  21. 8
      implementations/javascript/packages/core/src/strip.ts
  22. 8
      implementations/javascript/packages/core/src/values.ts
  23. 120
      implementations/javascript/packages/core/test/codec.test.ts
  24. 14
      implementations/javascript/packages/core/test/reader.test.ts
  25. 4
      implementations/javascript/packages/core/test/values.test.ts
  26. 4
      implementations/javascript/packages/schema/package.json
  27. 10
      implementations/javascript/packages/schema/src/compiler.ts
  28. 4
      implementations/javascript/packages/schema/src/compiler/context.ts
  29. 12
      implementations/javascript/packages/schema/src/compiler/genconverter.ts
  30. 4
      implementations/javascript/packages/schema/src/compiler/gentype.ts
  31. 10
      implementations/javascript/packages/schema/src/compiler/genunconverter.ts
  32. 4
      implementations/javascript/packages/schema/src/compiler/type.ts
  33. 22
      implementations/javascript/packages/schema/src/compiler/value.ts
  34. 123
      implementations/javascript/packages/schema/src/gen/schema.ts
  35. 28
      implementations/javascript/packages/schema/src/reader.ts
  36. 16
      implementations/python/preserves/preserves.py
  37. 22
      implementations/python/preserves/test_preserves.py
  38. 2
      implementations/python/setup.py
  39. 2
      implementations/racket/preserves/Makefile
  40. 6
      implementations/racket/preserves/preserves/jelly.rkt
  41. 6
      implementations/racket/preserves/preserves/main.rkt
  42. 14
      implementations/racket/preserves/preserves/read-binary.rkt
  43. 14
      implementations/racket/preserves/preserves/read-text.rkt
  44. 36
      implementations/racket/preserves/preserves/tests/test-main.rkt
  45. 12
      implementations/racket/preserves/preserves/tool.rkt
  46. 10
      implementations/racket/preserves/preserves/write-binary.rkt
  47. 10
      implementations/racket/preserves/preserves/write-text.rkt
  48. 2
      implementations/rust/preserves/Cargo.toml
  49. 2
      implementations/rust/preserves/src/error.rs
  50. 6
      implementations/rust/preserves/src/value/packed/constants.rs
  51. 8
      implementations/rust/preserves/src/value/packed/reader.rs
  52. 16
      implementations/rust/preserves/src/value/packed/writer.rs
  53. 12
      implementations/rust/preserves/src/value/reader.rs
  54. 10
      implementations/rust/preserves/src/value/writer.rs
  55. 2
      implementations/rust/preserves/tests/samples_tests.rs
  56. 68
      preserves.md
  57. 6
      schema/schema.bin
  58. 11
      schema/schema.prs
  59. BIN
      tests/samples.bin
  60. 6
      tests/samples.pr

2
canonical-binary.md

@ -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.

2
implementations/javascript/packages/core/package.json

@ -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",

10
implementations/javascript/packages/core/src/annotated.ts

@ -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;
}

4
implementations/javascript/packages/core/src/bytes.ts

@ -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;
}

4
implementations/javascript/packages/core/src/compound.ts

@ -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));
}

2
implementations/javascript/packages/core/src/constants.ts

@ -5,7 +5,7 @@ export enum Tag {
Double,
End,
Annotation,
Pointer,
Embedded,
SmallInteger_lo = 0x90,
MediumInteger_lo = 0xa0,

50
implementations/javascript/packages/core/src/decoder.ts

@ -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>;
}

22
implementations/javascript/packages/core/src/dictionary.ts

@ -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';
}
}

22
implementations/javascript/packages/core/src/pointer.ts → implementations/javascript/packages/core/src/embedded.ts

@ -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) {

50
implementations/javascript/packages/core/src/embeddedTypes.ts

@ -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);

50
implementations/javascript/packages/core/src/encoder.ts

@ -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 });
}

6
implementations/javascript/packages/core/src/float.ts

@ -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;
}

14
implementations/javascript/packages/core/src/fold.ts

@ -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>

8
implementations/javascript/packages/core/src/fromjs.ts

@ -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)));

4
implementations/javascript/packages/core/src/is.ts

@ -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];
}

10
implementations/javascript/packages/core/src/merge.ts

@ -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);
},

50
implementations/javascript/packages/core/src/pointerTypes.ts

@ -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);

34
implementations/javascript/packages/core/src/reader.ts

@ -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);
}

20
implementations/javascript/packages/core/src/record.ts

@ -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
implementations/javascript/packages/core/src/runtime.ts

@ -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';

8
implementations/javascript/packages/core/src/strip.ts

@ -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>
{

8
implementations/javascript/packages/core/src/values.ts

@ -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>,

120
implementations/javascript/packages/core/test/codec.test.ts

@ -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>;
} | {