From 574209966bee9369dcb25d9ab4758aa5397b77bc Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 26 Jan 2022 16:03:13 +0100 Subject: [PATCH] Better stringification --- .../javascript/packages/core/src/embedded.ts | 1 - .../javascript/packages/core/src/encoder.ts | 4 --- .../javascript/packages/core/src/text.ts | 25 ++++++++++++++-- .../javascript/packages/core/src/writer.ts | 29 ++++++++++++------- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/implementations/javascript/packages/core/src/embedded.ts b/implementations/javascript/packages/core/src/embedded.ts index 705b36d..1df670f 100644 --- a/implementations/javascript/packages/core/src/embedded.ts +++ b/implementations/javascript/packages/core/src/embedded.ts @@ -5,7 +5,6 @@ import { ReaderStateOptions } from "./reader"; export type EmbeddedTypeEncode = { encode(s: EncoderState, v: T): void; - toValue(v: T): Value; } export type EmbeddedTypeDecode = { diff --git a/implementations/javascript/packages/core/src/encoder.ts b/implementations/javascript/packages/core/src/encoder.ts index a3ce94f..011fa56 100644 --- a/implementations/javascript/packages/core/src/encoder.ts +++ b/implementations/javascript/packages/core/src/encoder.ts @@ -48,10 +48,6 @@ export function embeddedId(v: any): number { export const identityEmbeddedTypeEncode: EmbeddedTypeEncode = { encode(s: EncoderState, v: any): void { new Encoder(s, this).push(embeddedId(v)); - }, - - toValue(v: any): Value { - return embeddedId(v); } }; diff --git a/implementations/javascript/packages/core/src/text.ts b/implementations/javascript/packages/core/src/text.ts index 2117137..158f670 100644 --- a/implementations/javascript/packages/core/src/text.ts +++ b/implementations/javascript/packages/core/src/text.ts @@ -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 = { + 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(x: any, options?: WriterOptions): string { + options = { ... (options ?? {}) }; + options.embeddedWrite = options.embeddedWrite ?? stringifyEmbeddedWrite; return Writer.stringify(x as Writable, options); } diff --git a/implementations/javascript/packages/core/src/writer.ts b/implementations/javascript/packages/core/src/writer.ts index 7de2eeb..be55d34 100644 --- a/implementations/javascript/packages/core/src/writer.ts +++ b/implementations/javascript/packages/core/src/writer.ts @@ -19,7 +19,10 @@ function isIterable(v: any): v is Iterable { return typeof v === 'object' && v !== null && typeof v[Symbol.iterator] === 'function'; } -export const genericEmbeddedTypeEncode: EmbeddedTypeEncode = { +export type EmbeddedWriter = + { write(s: WriterState, v: T): void } | { toValue(v: T): Value }; + +export const genericEmbeddedTypeEncode: EmbeddedTypeEncode & EmbeddedWriter = { encode(s: EncoderState, v: GenericEmbedded): void { new Encoder(s, this).push(v.generic); }, @@ -29,13 +32,13 @@ export const genericEmbeddedTypeEncode: EmbeddedTypeEncode = { } }; -export const neverEmbeddedTypeEncode: EmbeddedTypeEncode = { +export const neverEmbeddedTypeEncode: EmbeddedTypeEncode & EmbeddedWriter = { encode(_s: EncoderState, _v: never): void { throw new Error("Embeddeds not permitted encoding Preserves document"); }, toValue(_v: never): Value { - 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 extends WriterStateOptions { - embeddedEncode?: EmbeddedTypeEncode; + embeddedWrite?: EmbeddedWriter; } export class WriterState { @@ -225,20 +228,20 @@ export function encodeBase64(bs: Uint8Array): string { export class Writer { state: WriterState; - embeddedType: EmbeddedTypeEncode; + embeddedWrite: EmbeddedWriter; - constructor(state: WriterState, embeddedType: EmbeddedTypeEncode); + constructor(state: WriterState, embeddedWrite: EmbeddedWriter); constructor(options?: WriterOptions); constructor( state_or_options: (WriterState | WriterOptions) = {}, - embeddedType?: EmbeddedTypeEncode + embeddedWrite?: EmbeddedWriter ) { 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 { else { ((v: Embedded) => { 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;