Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
389 changes: 184 additions & 205 deletions README.md

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lcweden/jsontext",
"version": "0.1.0",
"version": "0.2.0",
"license": "MIT",
"tasks": {
"bench": "deno bench --allow-all",
Expand All @@ -15,8 +15,15 @@
},
"exports": { ".": "./src/index.ts" },
"fmt": { "lineWidth": 100 },
"lint": { "rules": { "tags": ["recommended"], "include": ["no-slow-types"] } },
"exclude": ["node_modules/", "public/", "dist/", "vite.config.ts"],
"lint": {
"rules": {
"tags": ["recommended"],
"include": ["no-slow-types"],
"exclude": ["no-sloppy-imports"]
}
},
"unstable": ["sloppy-imports"],
"exclude": ["node_modules/", "public/", "dist/"],
"publish": {
"include": ["src/", "README.md", "LICENSE", "deno.json"],
"exclude": ["tests/", ".github/", ".vscode/", "dist/", "public/"]
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsontext",
"version": "0.1.0",
"version": "0.2.0",
"license": "MIT",
"description": "State machine for incremental JSON processing.",
"keywords": ["json", "stream"],
Expand Down Expand Up @@ -38,6 +38,7 @@
"test": "deno task test"
},
"sideEffects": false,
"engines": { "node": ">=18" },
"devDependencies": {
"@types/node": "^25.9.1",
"typescript": "~6.0.2",
Expand Down
12 changes: 6 additions & 6 deletions src/api/decoder.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { DEFAULT_DECODER_OPTIONS } from "#src/common/constants.ts";
import Decoder from "#src/modules/decoder.ts";
import type Token from "#src/modules/token.ts";
import type Value from "#src/modules/value.ts";
import type { Kind } from "#src/types/kind.ts";
import type { DecoderOptions } from "#src/types/options.ts";
import { DEFAULT_DECODER_OPTIONS } from "#src/common/constants";
import Decoder from "#src/modules/decoder";
import type Token from "#src/modules/token";
import type Value from "#src/modules/value";
import type { Kind } from "#src/types/kind";
import type { DecoderOptions } from "#src/types/options";

type JSONTextDecoderOptions = DecoderOptions;

Expand Down
30 changes: 14 additions & 16 deletions src/api/encoder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DEFAULT_ENCODER_OPTIONS } from "#src/common/constants.ts";
import Encoder from "#src/modules/encoder.ts";
import type Token from "#src/modules/token.ts";
import type Value from "#src/modules/value.ts";
import type { EncoderOptions } from "#src/types/options.ts";
import { DEFAULT_ENCODER_OPTIONS } from "#src/common/constants";
import Encoder from "#src/modules/encoder";
import type Token from "#src/modules/token";
import type Value from "#src/modules/value";
import type { EncoderOptions } from "#src/types/options";

type JSONTextEncoderOptions = EncoderOptions;

Expand All @@ -23,17 +23,6 @@ class JSONTextEncoder {
this.#encoder = new Encoder({ ...DEFAULT_ENCODER_OPTIONS, ...options });
}

/**
* Returns the cumulative encoded bytes produced so far.
*
* The buffer is never cleared between calls; use {@link reset} to start fresh.
*
* @returns The cumulative encoded bytes produced so far.
*/
bytes(): Uint8Array {
return this.#encoder.bytes();
}

/**
* The current nesting depth — `0` at top level, incremented inside each
* object or array.
Expand Down Expand Up @@ -79,6 +68,15 @@ class JSONTextEncoder {
return this.#encoder.stackPointer(where).toString();
}

/**
* Drains and returns the bytes accumulated in the output buffer since the
* last call. The internal buffer is cleared; structural state (nesting,
* delimiters) is preserved so subsequent writes continue the same document.
*/
takeBytes(): Uint8Array {
return this.#encoder.takeBytes();
}

/**
* Encodes a single {@link Token} and appends its bytes to the output buffer.
*
Expand Down
34 changes: 17 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
export type { JSONTextDecoderOptions } from "#src/api/decoder.ts";
export type { JSONTextEncoderOptions } from "#src/api/encoder.ts";
export type { JSONTextDecoderStreamOptions } from "#src/libs/stream-decoder.ts";
export type { JSONTextEncoderStreamOptions } from "#src/libs/stream-encoder.ts";
export type { JSONTextLineStreamOptions } from "#src/libs/stream-line.ts";
export type { JSONTextSelectorStreamOptions } from "#src/libs/stream-selector.ts";
export type { JSONTextDecoderOptions } from "#src/api/decoder";
export type { JSONTextEncoderOptions } from "#src/api/encoder";
export type { JSONTextDecoderStreamOptions } from "#src/libs/stream-decoder";
export type { JSONTextEncoderStreamOptions } from "#src/libs/stream-encoder";
export type { JSONTextLineStreamOptions } from "#src/libs/stream-line";
export type { JSONTextSelectorStreamOptions } from "#src/libs/stream-selector";

export type { Kind } from "#src/types/kind.ts";
export type { Kind } from "#src/types/kind";

export { default as JSONTextDecoder } from "#src/api/decoder.ts";
export { default as JSONTextEncoder } from "#src/api/encoder.ts";
export { default as Token } from "#src/modules/token.ts";
export { default as Value } from "#src/modules/value.ts";
export { default as JSONTextDecoder } from "#src/api/decoder";
export { default as JSONTextEncoder } from "#src/api/encoder";
export { default as Token } from "#src/modules/token";
export { default as Value } from "#src/modules/value";

export { default as JSONTextDecoderStream } from "#src/libs/stream-decoder.ts";
export { default as JSONTextEncoderStream } from "#src/libs/stream-encoder.ts";
export { default as JSONTextLineStream } from "#src/libs/stream-line.ts";
export { default as JSONTextSelectorStream } from "#src/libs/stream-selector.ts";
export { default as JSONTextDecoderStream } from "#src/libs/stream-decoder";
export { default as JSONTextEncoderStream } from "#src/libs/stream-encoder";
export { default as JSONTextLineStream } from "#src/libs/stream-line";
export { default as JSONTextSelectorStream } from "#src/libs/stream-selector";

export { KIND } from "#src/common/constants.ts";
export { SyntacticError } from "#src/common/errors.ts";
export { KIND } from "#src/common/constants";
export { SyntacticError } from "#src/common/errors";
8 changes: 4 additions & 4 deletions src/libs/stream-decoder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DEFAULT_DECODER_OPTIONS } from "#src/common/constants.ts";
import Decoder from "#src/modules/decoder.ts";
import type Token from "#src/modules/token.ts";
import type { DecoderOptions } from "#src/types/options.ts";
import { DEFAULT_DECODER_OPTIONS } from "#src/common/constants";
import Decoder from "#src/modules/decoder";
import type Token from "#src/modules/token";
import type { DecoderOptions } from "#src/types/options";

type JSONTextDecoderStreamOptions = DecoderOptions & {
writableStrategy?: QueuingStrategy<Uint8Array>;
Expand Down
8 changes: 4 additions & 4 deletions src/libs/stream-encoder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DEFAULT_ENCODER_OPTIONS } from "#src/common/constants.ts";
import Encoder from "#src/modules/encoder.ts";
import type Token from "#src/modules/token.ts";
import type { EncoderOptions } from "#src/types/options.ts";
import { DEFAULT_ENCODER_OPTIONS } from "#src/common/constants";
import Encoder from "#src/modules/encoder";
import type Token from "#src/modules/token";
import type { EncoderOptions } from "#src/types/options";

type JSONTextEncoderStreamOptions = EncoderOptions & {
writableStrategy?: QueuingStrategy<Token>;
Expand Down
8 changes: 4 additions & 4 deletions src/libs/stream-line.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DEFAULT_DECODER_OPTIONS } from "#src/common/constants.ts";
import Decoder from "#src/modules/decoder.ts";
import type Value from "#src/modules/value.ts";
import type { DecoderOptions } from "#src/types/options.ts";
import { DEFAULT_DECODER_OPTIONS } from "#src/common/constants";
import Decoder from "#src/modules/decoder";
import type Value from "#src/modules/value";
import type { DecoderOptions } from "#src/types/options";

type JSONTextLineStreamOptions = DecoderOptions & {
writableStrategy?: QueuingStrategy<Uint8Array>;
Expand Down
14 changes: 7 additions & 7 deletions src/libs/stream-selector.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { DEFAULT_DECODER_OPTIONS, KIND, MAX_NESTING_DEPTH } from "#src/common/constants.ts";
import Decoder from "#src/modules/decoder.ts";
import type { Matcher } from "#src/modules/path.ts";
import Path from "#src/modules/path.ts";
import type Value from "#src/modules/value.ts";
import type { DecoderOptions } from "#src/types/options.ts";
import { encodeText } from "#src/utils/text.ts";
import { DEFAULT_DECODER_OPTIONS, KIND, MAX_NESTING_DEPTH } from "#src/common/constants";
import Decoder from "#src/modules/decoder";
import type { Matcher } from "#src/modules/path";
import Path from "#src/modules/path";
import type Value from "#src/modules/value";
import type { DecoderOptions } from "#src/types/options";
import { encodeText } from "#src/utils/text";

type JSONTextSelectorStreamOptions = DecoderOptions & {
writableStrategy?: QueuingStrategy<Uint8Array>;
Expand Down
6 changes: 3 additions & 3 deletions src/modules/automaton.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MAX_NESTING_DEPTH } from "#src/common/constants.ts";
import Entry from "#src/modules/entry.ts";
import type { Kind } from "#src/types/kind.ts";
import { MAX_NESTING_DEPTH } from "#src/common/constants";
import Entry from "#src/modules/entry";
import type { Kind } from "#src/types/kind";

class Automaton {
#last: Entry;
Expand Down
24 changes: 12 additions & 12 deletions src/modules/decoder.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ASCII, KIND } from "#src/common/constants.ts";
import { SyntacticError } from "#src/common/errors.ts";
import Cursor from "#src/modules/cursor.ts";
import type Pointer from "#src/modules/pointer.ts";
import State from "#src/modules/state.ts";
import Token from "#src/modules/token.ts";
import Value from "#src/modules/value.ts";
import type { Kind } from "#src/types/kind.ts";
import type { DecoderOptions } from "#src/types/options.ts";
import { normalize } from "#src/utils/kind.ts";
import { decodeText } from "#src/utils/text.ts";
import { ASCII, KIND } from "#src/common/constants";
import { SyntacticError } from "#src/common/errors";
import Cursor from "#src/modules/cursor";
import type Pointer from "#src/modules/pointer";
import State from "#src/modules/state";
import Token from "#src/modules/token";
import Value from "#src/modules/value";
import type { Kind } from "#src/types/kind";
import type { DecoderOptions } from "#src/types/options";
import { normalize } from "#src/utils/kind";
import { decodeText } from "#src/utils/text";
import {
consumeFalse,
consumeNull,
Expand All @@ -18,7 +18,7 @@ import {
consumeString,
consumeTrue,
consumeWhitespace,
} from "#src/utils/wire.ts";
} from "#src/utils/wire";

class Decoder {
#cursor: Cursor;
Expand Down
20 changes: 10 additions & 10 deletions src/modules/encoder.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ASCII, KIND, UNICODE } from "#src/common/constants.ts";
import { SyntacticError } from "#src/common/errors.ts";
import type Pointer from "#src/modules/pointer.ts";
import State from "#src/modules/state.ts";
import Tape from "#src/modules/tape.ts";
import Token from "#src/modules/token.ts";
import Value from "#src/modules/value.ts";
import type { Kind } from "#src/types/kind.ts";
import type { EncoderOptions } from "#src/types/options.ts";
import { decodeText, encodeText } from "#src/utils/text.ts";
import { ASCII, KIND, UNICODE } from "#src/common/constants";
import { SyntacticError } from "#src/common/errors";
import type Pointer from "#src/modules/pointer";
import State from "#src/modules/state";
import Tape from "#src/modules/tape";
import Token from "#src/modules/token";
import Value from "#src/modules/value";
import type { Kind } from "#src/types/kind";
import type { EncoderOptions } from "#src/types/options";
import { decodeText, encodeText } from "#src/utils/text";

class Encoder {
#tape: Tape;
Expand Down
4 changes: 2 additions & 2 deletions src/modules/entry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { KIND } from "#src/common/constants.ts";
import type { Kind } from "#src/types/kind.ts";
import { KIND } from "#src/common/constants";
import type { Kind } from "#src/types/kind";

class Entry {
#type: "object" | "array";
Expand Down
8 changes: 4 additions & 4 deletions src/modules/path.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ASCII, SEGMENT, SELECTOR } from "#src/common/constants.ts";
import { ASCII, SEGMENT, SELECTOR } from "#src/common/constants";
import type {
ArraySliceSelector,
IndexSelector,
NameSelector,
Segment,
Selector,
WildcardSelector,
} from "#src/types/path.ts";
import { decodeText } from "#src/utils/text.ts";
import { consumeNumber, consumeWhitespace } from "#src/utils/wire.ts";
} from "#src/types/path";
import { decodeText } from "#src/utils/text";
import { consumeNumber, consumeWhitespace } from "#src/utils/wire";

/**
* Supports a subset of JSON Path syntax and provides an NFA-based matcher.
Expand Down
10 changes: 5 additions & 5 deletions src/modules/state.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Automaton from "#src/modules/automaton.ts";
import Pointer from "#src/modules/pointer.ts";
import { ObjectNamespaceStack, ObjectNameStack } from "#src/modules/stack.ts";
import type { Kind } from "#src/types/kind.ts";
import type { BaseOptions } from "#src/types/options.ts";
import Automaton from "#src/modules/automaton";
import Pointer from "#src/modules/pointer";
import { ObjectNamespaceStack, ObjectNameStack } from "#src/modules/stack";
import type { Kind } from "#src/types/kind";
import type { BaseOptions } from "#src/types/options";

class State {
#automaton: Automaton;
Expand Down
8 changes: 4 additions & 4 deletions src/modules/token.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { KIND } from "#src/common/constants.ts";
import type { Kind } from "#src/types/kind.ts";
import { normalize } from "#src/utils/kind.ts";
import { decodeText, encodeText } from "#src/utils/text.ts";
import { KIND } from "#src/common/constants";
import type { Kind } from "#src/types/kind";
import { normalize } from "#src/utils/kind";
import { decodeText, encodeText } from "#src/utils/text";

/**
* Represents a single JSON token.
Expand Down
14 changes: 7 additions & 7 deletions src/modules/value.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ASCII, DEFAULT_DECODER_OPTIONS, KIND } from "#src/common/constants.ts";
import Decoder from "#src/modules/decoder.ts";
import type Token from "#src/modules/token.ts";
import type { Kind } from "#src/types/kind.ts";
import { normalize } from "#src/utils/kind.ts";
import { decodeText, encodeText } from "#src/utils/text.ts";
import { compareUTF16, consumeWhitespace } from "#src/utils/wire.ts";
import { ASCII, DEFAULT_DECODER_OPTIONS, KIND } from "#src/common/constants";
import Decoder from "#src/modules/decoder";
import type Token from "#src/modules/token";
import type { Kind } from "#src/types/kind";
import { normalize } from "#src/utils/kind";
import { decodeText, encodeText } from "#src/utils/text";
import { compareUTF16, consumeWhitespace } from "#src/utils/wire";

/**
* Represents a complete JSON value.
Expand Down
2 changes: 1 addition & 1 deletion src/types/kind.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import type { KIND } from "#src/common/constants.ts";
import type { KIND } from "#src/common/constants";

export type Kind = typeof KIND[keyof typeof KIND];
2 changes: 1 addition & 1 deletion src/types/path.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IDENTIFIER, SEGMENT, SELECTOR } from "#src/common/constants.ts";
import { IDENTIFIER, SEGMENT, SELECTOR } from "#src/common/constants";

export type NameSelector = { type: typeof SELECTOR.NAME; name: string };

Expand Down
4 changes: 2 additions & 2 deletions src/utils/kind.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ASCII, KIND } from "#src/common/constants.ts";
import type { Kind } from "#src/types/kind.ts";
import { ASCII, KIND } from "#src/common/constants";
import type { Kind } from "#src/types/kind";

const NORM_KIND: Record<number, Kind> = {
[ASCII.LOWER_CASE_N]: KIND.NULL,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/wire.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ASCII } from "#src/common/constants.ts";
import { decodeText } from "#src/utils/text.ts";
import { ASCII } from "#src/common/constants";
import { decodeText } from "#src/utils/text";

/**
* Compares two strings by UTF-16 code unit order, as required by RFC 8785 §3.2.3.
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/correctness.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { KIND } from "#src/common/constants.ts";
import { JSONTextDecoderStream, JSONTextLineStream, Token } from "#src/index.ts";
import { KIND } from "#src/common/constants";
import { JSONTextDecoderStream, JSONTextLineStream, Token } from "#src/index";
import { assert, assertEquals } from "#std/assert";

const GITHUB_TOKEN = Deno.env.get("GITHUB_TOKEN");
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/query.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { KIND } from "#src/common/constants.ts";
import { JSONTextSelectorStream } from "#src/index.ts";
import { KIND } from "#src/common/constants";
import { JSONTextSelectorStream } from "#src/index";
import { assert, assertEquals } from "#std/assert";

const GITHUB_TOKEN = Deno.env.get("GITHUB_TOKEN");
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/round-trip.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { KIND } from "#src/common/constants.ts";
import { JSONTextSelectorStream } from "#src/index.ts";
import { KIND } from "#src/common/constants";
import { JSONTextSelectorStream } from "#src/index";
import { assert, assertEquals } from "#std/assert";

const GITHUB_TOKEN = Deno.env.get("GITHUB_TOKEN");
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/streaming.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JSONTextDecoderStream } from "#src/index.ts";
import { JSONTextDecoderStream } from "#src/index";
import { assert } from "#std/assert";

const GITHUB_TOKEN = Deno.env.get("GITHUB_TOKEN");
Expand Down
Loading