mirror of
https://github.com/voson-wang/toon.git
synced 2026-01-29 23:34:10 +08:00
perf: consolidate array & header encoding functions
This commit is contained in:
@@ -18,10 +18,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
encodeKey,
|
encodeKey,
|
||||||
encodePrimitive,
|
encodePrimitive,
|
||||||
formatArrayHeader,
|
formatHeader,
|
||||||
formatKeyedArrayHeader,
|
|
||||||
formatKeyedTableHeader,
|
|
||||||
formatTabularHeader,
|
|
||||||
joinEncodedValues,
|
joinEncodedValues,
|
||||||
} from './primitives'
|
} from './primitives'
|
||||||
import { LineWriter } from './writer'
|
import { LineWriter } from './writer'
|
||||||
@@ -36,7 +33,7 @@ export function encodeValue(value: JsonValue, options: ResolvedEncodeOptions): s
|
|||||||
const writer = new LineWriter(options.indent)
|
const writer = new LineWriter(options.indent)
|
||||||
|
|
||||||
if (isJsonArray(value)) {
|
if (isJsonArray(value)) {
|
||||||
encodeRootArray(value, writer, options)
|
encodeArray(undefined, value, writer, 0, options)
|
||||||
}
|
}
|
||||||
else if (isJsonObject(value)) {
|
else if (isJsonObject(value)) {
|
||||||
encodeObject(value, writer, 0, options)
|
encodeObject(value, writer, 0, options)
|
||||||
@@ -64,7 +61,7 @@ export function encodeKeyValuePair(key: string, value: JsonValue, writer: LineWr
|
|||||||
writer.push(depth, `${encodedKey}: ${encodePrimitive(value, options.delimiter)}`)
|
writer.push(depth, `${encodedKey}: ${encodePrimitive(value, options.delimiter)}`)
|
||||||
}
|
}
|
||||||
else if (isJsonArray(value)) {
|
else if (isJsonArray(value)) {
|
||||||
encodeArrayProperty(key, value, writer, depth, options)
|
encodeArray(key, value, writer, depth, options)
|
||||||
}
|
}
|
||||||
else if (isJsonObject(value)) {
|
else if (isJsonObject(value)) {
|
||||||
const nestedKeys = Object.keys(value)
|
const nestedKeys = Object.keys(value)
|
||||||
@@ -83,47 +80,21 @@ export function encodeKeyValuePair(key: string, value: JsonValue, writer: LineWr
|
|||||||
|
|
||||||
// #region Array encoding
|
// #region Array encoding
|
||||||
|
|
||||||
export function encodeRootArray(value: JsonArray, writer: LineWriter, options: ResolvedEncodeOptions): void {
|
export function encodeArray(
|
||||||
|
key: string | undefined,
|
||||||
|
value: JsonArray,
|
||||||
|
writer: LineWriter,
|
||||||
|
depth: Depth,
|
||||||
|
options: ResolvedEncodeOptions,
|
||||||
|
): void {
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
writer.push(0, '[0]:')
|
if (key === undefined) {
|
||||||
return
|
writer.push(depth, '[0]:')
|
||||||
}
|
|
||||||
|
|
||||||
// Primitive array
|
|
||||||
if (isArrayOfPrimitives(value)) {
|
|
||||||
encodeInlinePrimitiveArray(undefined, value, writer, 0, options)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Array of arrays (all primitives)
|
|
||||||
if (isArrayOfArrays(value)) {
|
|
||||||
const allPrimitiveArrays = value.every(arr => isArrayOfPrimitives(arr))
|
|
||||||
if (allPrimitiveArrays) {
|
|
||||||
encodeArrayOfArraysAsListItems(undefined, value, writer, 0, options)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Array of objects
|
|
||||||
if (isArrayOfObjects(value)) {
|
|
||||||
const header = detectTabularHeader(value)
|
|
||||||
if (header) {
|
|
||||||
encodeArrayOfObjectsAsTabular(undefined, value, header, writer, 0, options)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
encodeArrayOfObjectsAsListItems(undefined, value, writer, 0, options)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mixed array: fallback to expanded format (not in spec, but safe default)
|
|
||||||
encodeMixedArrayAsListItems(undefined, value, writer, 0, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function encodeArrayProperty(key: string, value: JsonArray, writer: LineWriter, depth: Depth, options: ResolvedEncodeOptions): void {
|
|
||||||
if (value.length === 0) {
|
|
||||||
const encodedKey = encodeKey(key)
|
const encodedKey = encodeKey(key)
|
||||||
writer.push(depth, `${encodedKey}[0]:`)
|
writer.push(depth, `${encodedKey}[0]:`)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +120,7 @@ export function encodeArrayProperty(key: string, value: JsonArray, writer: LineW
|
|||||||
encodeArrayOfObjectsAsTabular(key, value, header, writer, depth, options)
|
encodeArrayOfObjectsAsTabular(key, value, header, writer, depth, options)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
encodeArrayOfObjectsAsListItems(key, value, writer, depth, options)
|
encodeMixedArrayAsListItems(key, value, writer, depth, options)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -169,7 +140,7 @@ export function encodeInlinePrimitiveArray(
|
|||||||
depth: Depth,
|
depth: Depth,
|
||||||
options: ResolvedEncodeOptions,
|
options: ResolvedEncodeOptions,
|
||||||
): void {
|
): void {
|
||||||
const header = prefix ? formatKeyedArrayHeader(prefix, values.length) : formatArrayHeader(values.length)
|
const header = formatHeader(values.length, prefix ? { key: prefix } : undefined)
|
||||||
const joinedValue = joinEncodedValues(values, options.delimiter)
|
const joinedValue = joinEncodedValues(values, options.delimiter)
|
||||||
// Only add space if there are values
|
// Only add space if there are values
|
||||||
if (values.length === 0) {
|
if (values.length === 0) {
|
||||||
@@ -191,7 +162,7 @@ export function encodeArrayOfArraysAsListItems(
|
|||||||
depth: Depth,
|
depth: Depth,
|
||||||
options: ResolvedEncodeOptions,
|
options: ResolvedEncodeOptions,
|
||||||
): void {
|
): void {
|
||||||
const header = prefix ? formatKeyedArrayHeader(prefix, values.length) : formatArrayHeader(values.length)
|
const header = formatHeader(values.length, prefix ? { key: prefix } : undefined)
|
||||||
writer.push(depth, header)
|
writer.push(depth, header)
|
||||||
|
|
||||||
for (const arr of values) {
|
for (const arr of values) {
|
||||||
@@ -203,7 +174,7 @@ export function encodeArrayOfArraysAsListItems(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatInlineArray(values: readonly JsonPrimitive[], delimiter: string): string {
|
export function formatInlineArray(values: readonly JsonPrimitive[], delimiter: string): string {
|
||||||
const header = formatArrayHeader(values.length)
|
const header = formatHeader(values.length)
|
||||||
const joinedValue = joinEncodedValues(values, delimiter)
|
const joinedValue = joinEncodedValues(values, delimiter)
|
||||||
// Only add space if there are values
|
// Only add space if there are values
|
||||||
if (values.length === 0) {
|
if (values.length === 0) {
|
||||||
@@ -224,9 +195,7 @@ export function encodeArrayOfObjectsAsTabular(
|
|||||||
depth: Depth,
|
depth: Depth,
|
||||||
options: ResolvedEncodeOptions,
|
options: ResolvedEncodeOptions,
|
||||||
): void {
|
): void {
|
||||||
const headerStr = prefix
|
const headerStr = formatHeader(rows.length, { key: prefix, fields: header })
|
||||||
? formatKeyedTableHeader(prefix, rows.length, header)
|
|
||||||
: formatTabularHeader(rows.length, header)
|
|
||||||
writer.push(depth, `${headerStr}`)
|
writer.push(depth, `${headerStr}`)
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
@@ -287,7 +256,7 @@ export function encodeMixedArrayAsListItems(
|
|||||||
depth: Depth,
|
depth: Depth,
|
||||||
options: ResolvedEncodeOptions,
|
options: ResolvedEncodeOptions,
|
||||||
): void {
|
): void {
|
||||||
const header = prefix ? formatKeyedArrayHeader(prefix, items.length) : formatArrayHeader(items.length)
|
const header = formatHeader(items.length, prefix ? { key: prefix } : undefined)
|
||||||
writer.push(depth, header)
|
writer.push(depth, header)
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
@@ -309,21 +278,6 @@ export function encodeMixedArrayAsListItems(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodeArrayOfObjectsAsListItems(
|
|
||||||
prefix: string | undefined,
|
|
||||||
rows: readonly JsonObject[],
|
|
||||||
writer: LineWriter,
|
|
||||||
depth: Depth,
|
|
||||||
options: ResolvedEncodeOptions,
|
|
||||||
): void {
|
|
||||||
const header = prefix ? formatKeyedArrayHeader(prefix, rows.length) : formatArrayHeader(rows.length)
|
|
||||||
writer.push(depth, `${header}`)
|
|
||||||
|
|
||||||
for (const obj of rows) {
|
|
||||||
encodeObjectAsListItem(obj, writer, depth + 1, options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function encodeObjectAsListItem(obj: JsonObject, writer: LineWriter, depth: Depth, options: ResolvedEncodeOptions): void {
|
export function encodeObjectAsListItem(obj: JsonObject, writer: LineWriter, depth: Depth, options: ResolvedEncodeOptions): void {
|
||||||
const keys = Object.keys(obj)
|
const keys = Object.keys(obj)
|
||||||
if (keys.length === 0) {
|
if (keys.length === 0) {
|
||||||
|
|||||||
@@ -131,24 +131,35 @@ export function joinEncodedValues(values: readonly JsonPrimitive[], delimiter: s
|
|||||||
|
|
||||||
// #region Header formatters
|
// #region Header formatters
|
||||||
|
|
||||||
export function formatArrayHeader(length: number): string {
|
/**
|
||||||
return `[${length}]:`
|
* Header formatter for arrays and tables with optional key prefix and field names
|
||||||
|
*/
|
||||||
|
export function formatHeader(
|
||||||
|
length: number,
|
||||||
|
options?: {
|
||||||
|
key?: string
|
||||||
|
fields?: readonly string[]
|
||||||
|
},
|
||||||
|
): string {
|
||||||
|
const key = options?.key
|
||||||
|
const fields = options?.fields
|
||||||
|
|
||||||
|
let header = ''
|
||||||
|
|
||||||
|
if (key) {
|
||||||
|
header += encodeKey(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatTabularHeader(length: number, fields: readonly string[]): string {
|
header += `[${length}]`
|
||||||
|
|
||||||
|
if (fields) {
|
||||||
const quotedFields = fields.map(f => encodeKey(f))
|
const quotedFields = fields.map(f => encodeKey(f))
|
||||||
return `[${length}]{${quotedFields.join(',')}}:`
|
header += `{${quotedFields.join(',')}}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatKeyedArrayHeader(key: string, length: number): string {
|
header += ':'
|
||||||
const encodedKey = encodeKey(key)
|
|
||||||
return `${encodedKey}[${length}]:`
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatKeyedTableHeader(key: string, length: number, fields: readonly string[]): string {
|
return header
|
||||||
const encodedKey = encodeKey(key)
|
|
||||||
const quotedFields = fields.map(f => encodeKey(f))
|
|
||||||
return `${encodedKey}[${length}]{${quotedFields.join(',')}}:`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|||||||
Reference in New Issue
Block a user