Better stringification
This commit is contained in:
parent
c5094f8b8f
commit
574209966b
|
@ -5,7 +5,6 @@ import { ReaderStateOptions } from "./reader";
|
||||||
|
|
||||||
export type EmbeddedTypeEncode<T> = {
|
export type EmbeddedTypeEncode<T> = {
|
||||||
encode(s: EncoderState, v: T): void;
|
encode(s: EncoderState, v: T): void;
|
||||||
toValue(v: T): Value<GenericEmbedded>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EmbeddedTypeDecode<T> = {
|
export type EmbeddedTypeDecode<T> = {
|
||||||
|
|
|
@ -48,10 +48,6 @@ export function embeddedId(v: any): number {
|
||||||
export const identityEmbeddedTypeEncode: EmbeddedTypeEncode<any> = {
|
export const identityEmbeddedTypeEncode: EmbeddedTypeEncode<any> = {
|
||||||
encode(s: EncoderState, v: any): void {
|
encode(s: EncoderState, v: any): void {
|
||||||
new Encoder(s, this).push(embeddedId(v));
|
new Encoder(s, this).push(embeddedId(v));
|
||||||
},
|
|
||||||
|
|
||||||
toValue(v: any): Value<GenericEmbedded> {
|
|
||||||
return embeddedId(v);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,33 @@
|
||||||
import type { GenericEmbedded } from './embedded';
|
import { GenericEmbedded } from './embedded';
|
||||||
import type { Value } from './values';
|
import type { Value } from './values';
|
||||||
|
|
||||||
import { Annotated } from './annotated';
|
import { Annotated } from './annotated';
|
||||||
import { Bytes } from './bytes';
|
import { Bytes } from './bytes';
|
||||||
import { KeyedDictionary, KeyedSet } from './dictionary';
|
import { KeyedDictionary, KeyedSet } from './dictionary';
|
||||||
import { Writer, Writable, WriterOptions } from './writer';
|
import { Writer, Writable, WriterOptions, EmbeddedWriter, WriterState } from './writer';
|
||||||
|
import { fromJS } from './fromjs';
|
||||||
|
|
||||||
|
export const stringifyEmbeddedWrite: EmbeddedWriter<any> = {
|
||||||
|
write(s: WriterState, v: any): void {
|
||||||
|
if (v instanceof GenericEmbedded) {
|
||||||
|
new Writer(s, this).push(v.generic);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const o = fromJS(v);
|
||||||
|
new Writer(s, this).push(v);
|
||||||
|
return;
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
s.pieces.push(JSON.stringify(v));
|
||||||
|
} catch {}
|
||||||
|
s.pieces.push('⌜' + v + '⌝');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export function stringify<T = GenericEmbedded>(x: any, options?: WriterOptions<T>): string {
|
export function stringify<T = GenericEmbedded>(x: any, options?: WriterOptions<T>): string {
|
||||||
|
options = { ... (options ?? {}) };
|
||||||
|
options.embeddedWrite = options.embeddedWrite ?? stringifyEmbeddedWrite;
|
||||||
return Writer.stringify(x as Writable<T>, options);
|
return Writer.stringify(x as Writable<T>, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,10 @@ function isIterable<T>(v: any): v is Iterable<T> {
|
||||||
return typeof v === 'object' && v !== null && typeof v[Symbol.iterator] === 'function';
|
return typeof v === 'object' && v !== null && typeof v[Symbol.iterator] === 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const genericEmbeddedTypeEncode: EmbeddedTypeEncode<GenericEmbedded> = {
|
export type EmbeddedWriter<T> =
|
||||||
|
{ write(s: WriterState, v: T): void } | { toValue(v: T): Value<GenericEmbedded> };
|
||||||
|
|
||||||
|
export const genericEmbeddedTypeEncode: EmbeddedTypeEncode<GenericEmbedded> & EmbeddedWriter<GenericEmbedded> = {
|
||||||
encode(s: EncoderState, v: GenericEmbedded): void {
|
encode(s: EncoderState, v: GenericEmbedded): void {
|
||||||
new Encoder(s, this).push(v.generic);
|
new Encoder(s, this).push(v.generic);
|
||||||
},
|
},
|
||||||
|
@ -29,13 +32,13 @@ export const genericEmbeddedTypeEncode: EmbeddedTypeEncode<GenericEmbedded> = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const neverEmbeddedTypeEncode: EmbeddedTypeEncode<never> = {
|
export const neverEmbeddedTypeEncode: EmbeddedTypeEncode<never> & EmbeddedWriter<never> = {
|
||||||
encode(_s: EncoderState, _v: never): void {
|
encode(_s: EncoderState, _v: never): void {
|
||||||
throw new Error("Embeddeds not permitted encoding Preserves document");
|
throw new Error("Embeddeds not permitted encoding Preserves document");
|
||||||
},
|
},
|
||||||
|
|
||||||
toValue(_v: never): Value<GenericEmbedded> {
|
toValue(_v: never): Value<GenericEmbedded> {
|
||||||
throw new Error("Embeddeds not permitted encoding Preserves document");
|
throw new Error("Embeddeds not permitted writing Preserves document");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,7 +50,7 @@ export interface WriterStateOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WriterOptions<T> extends WriterStateOptions {
|
export interface WriterOptions<T> extends WriterStateOptions {
|
||||||
embeddedEncode?: EmbeddedTypeEncode<T>;
|
embeddedWrite?: EmbeddedWriter<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class WriterState {
|
export class WriterState {
|
||||||
|
@ -225,20 +228,20 @@ export function encodeBase64(bs: Uint8Array): string {
|
||||||
|
|
||||||
export class Writer<T> {
|
export class Writer<T> {
|
||||||
state: WriterState;
|
state: WriterState;
|
||||||
embeddedType: EmbeddedTypeEncode<T>;
|
embeddedWrite: EmbeddedWriter<T>;
|
||||||
|
|
||||||
constructor(state: WriterState, embeddedType: EmbeddedTypeEncode<T>);
|
constructor(state: WriterState, embeddedWrite: EmbeddedWriter<T>);
|
||||||
constructor(options?: WriterOptions<T>);
|
constructor(options?: WriterOptions<T>);
|
||||||
constructor(
|
constructor(
|
||||||
state_or_options: (WriterState | WriterOptions<T>) = {},
|
state_or_options: (WriterState | WriterOptions<T>) = {},
|
||||||
embeddedType?: EmbeddedTypeEncode<T>
|
embeddedWrite?: EmbeddedWriter<T>
|
||||||
) {
|
) {
|
||||||
if (state_or_options instanceof WriterState) {
|
if (state_or_options instanceof WriterState) {
|
||||||
this.state = state_or_options;
|
this.state = state_or_options;
|
||||||
this.embeddedType = embeddedType!;
|
this.embeddedWrite = embeddedWrite!;
|
||||||
} else {
|
} else {
|
||||||
this.state = new WriterState(state_or_options);
|
this.state = new WriterState(state_or_options);
|
||||||
this.embeddedType = state_or_options.embeddedEncode ?? neverEmbeddedTypeEncode;
|
this.embeddedWrite = state_or_options.embeddedWrite ?? neverEmbeddedTypeEncode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,8 +318,12 @@ export class Writer<T> {
|
||||||
else {
|
else {
|
||||||
((v: Embedded<T>) => {
|
((v: Embedded<T>) => {
|
||||||
this.state.pieces.push('#!');
|
this.state.pieces.push('#!');
|
||||||
new Writer(this.state, genericEmbeddedTypeEncode)
|
if ('write' in this.embeddedWrite) {
|
||||||
.push(this.embeddedType.toValue(v.embeddedValue));
|
this.embeddedWrite.write(this.state, v.embeddedValue);
|
||||||
|
} else {
|
||||||
|
new Writer(this.state, genericEmbeddedTypeEncode)
|
||||||
|
.push(this.embeddedWrite.toValue(v.embeddedValue));
|
||||||
|
}
|
||||||
})(v);
|
})(v);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue