Better stringification
This commit is contained in:
parent
c5094f8b8f
commit
574209966b
|
@ -5,7 +5,6 @@ import { ReaderStateOptions } from "./reader";
|
|||
|
||||
export type EmbeddedTypeEncode<T> = {
|
||||
encode(s: EncoderState, v: T): void;
|
||||
toValue(v: T): Value<GenericEmbedded>;
|
||||
}
|
||||
|
||||
export type EmbeddedTypeDecode<T> = {
|
||||
|
|
|
@ -48,10 +48,6 @@ export function embeddedId(v: any): number {
|
|||
export const identityEmbeddedTypeEncode: EmbeddedTypeEncode<any> = {
|
||||
encode(s: EncoderState, v: any): void {
|
||||
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 { Annotated } from './annotated';
|
||||
import { Bytes } from './bytes';
|
||||
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 {
|
||||
options = { ... (options ?? {}) };
|
||||
options.embeddedWrite = options.embeddedWrite ?? stringifyEmbeddedWrite;
|
||||
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';
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
throw new Error("Embeddeds not permitted encoding Preserves document");
|
||||
},
|
||||
|
||||
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 {
|
||||
embeddedEncode?: EmbeddedTypeEncode<T>;
|
||||
embeddedWrite?: EmbeddedWriter<T>;
|
||||
}
|
||||
|
||||
export class WriterState {
|
||||
|
@ -225,20 +228,20 @@ export function encodeBase64(bs: Uint8Array): string {
|
|||
|
||||
export class Writer<T> {
|
||||
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(
|
||||
state_or_options: (WriterState | WriterOptions<T>) = {},
|
||||
embeddedType?: EmbeddedTypeEncode<T>
|
||||
embeddedWrite?: EmbeddedWriter<T>
|
||||
) {
|
||||
if (state_or_options instanceof WriterState) {
|
||||
this.state = state_or_options;
|
||||
this.embeddedType = embeddedType!;
|
||||
this.embeddedWrite = embeddedWrite!;
|
||||
} else {
|
||||
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 {
|
||||
((v: Embedded<T>) => {
|
||||
this.state.pieces.push('#!');
|
||||
new Writer(this.state, genericEmbeddedTypeEncode)
|
||||
.push(this.embeddedType.toValue(v.embeddedValue));
|
||||
if ('write' in this.embeddedWrite) {
|
||||
this.embeddedWrite.write(this.state, v.embeddedValue);
|
||||
} else {
|
||||
new Writer(this.state, genericEmbeddedTypeEncode)
|
||||
.push(this.embeddedWrite.toValue(v.embeddedValue));
|
||||
}
|
||||
})(v);
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue