jspurefix 5.9.1 → 5.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BACKPORT_PLAN.md +20 -7
- package/README.md +35 -0
- package/WORKLOG.md +119 -0
- package/dist/benchmark/bench-report.d.ts +5 -0
- package/dist/benchmark/bench-report.js +91 -0
- package/dist/benchmark/bench-report.js.map +1 -0
- package/dist/benchmark/bench-runner.d.ts +12 -0
- package/dist/benchmark/bench-runner.js +193 -0
- package/dist/benchmark/bench-runner.js.map +1 -0
- package/dist/benchmark/bench-stats.d.ts +10 -0
- package/dist/benchmark/bench-stats.js +56 -0
- package/dist/benchmark/bench-stats.js.map +1 -0
- package/dist/benchmark/bench-types.d.ts +74 -0
- package/dist/benchmark/bench-types.js +3 -0
- package/dist/benchmark/bench-types.js.map +1 -0
- package/dist/benchmark/gc-probe.d.ts +18 -0
- package/dist/benchmark/gc-probe.js +103 -0
- package/dist/benchmark/gc-probe.js.map +1 -0
- package/dist/benchmark/index.d.ts +6 -0
- package/dist/benchmark/index.js +23 -0
- package/dist/benchmark/index.js.map +1 -0
- package/dist/benchmark/parse-bench.d.ts +28 -0
- package/dist/benchmark/parse-bench.js +85 -0
- package/dist/benchmark/parse-bench.js.map +1 -0
- package/dist/buffer/ascii/ascii-encoder.d.ts +1 -0
- package/dist/buffer/ascii/ascii-encoder.js +15 -0
- package/dist/buffer/ascii/ascii-encoder.js.map +1 -1
- package/dist/buffer/ascii/ascii-parser.d.ts +1 -0
- package/dist/buffer/ascii/ascii-parser.js +4 -1
- package/dist/buffer/ascii/ascii-parser.js.map +1 -1
- package/dist/buffer/ascii/ascii-segment-parser.js +3 -2
- package/dist/buffer/ascii/ascii-segment-parser.js.map +1 -1
- package/dist/buffer/ascii/tag-index.js.map +1 -1
- package/dist/buffer/msg-encoder.d.ts +2 -0
- package/dist/buffer/msg-encoder.js +1 -0
- package/dist/buffer/msg-encoder.js.map +1 -1
- package/dist/buffer/msg-view.d.ts +1 -0
- package/dist/buffer/msg-view.js +25 -19
- package/dist/buffer/msg-view.js.map +1 -1
- package/dist/dictionary/parser/quickfix/dictionary-validator.d.ts +1 -1
- package/dist/dictionary/parser/quickfix/dictionary-validator.js.map +1 -1
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.d.ts +1 -1
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js +1 -2
- package/dist/dictionary/parser/quickfix/quick-fix-graph-parser.js.map +1 -1
- package/dist/dictionary/parser/quickfix/validation-error.d.ts +2 -2
- package/dist/dictionary/parser/quickfix/validation-error.js.map +1 -1
- package/dist/jsfix-bench.d.ts +1 -0
- package/dist/jsfix-bench.js +213 -0
- package/dist/jsfix-bench.js.map +1 -0
- package/dist/runtime/session-container.d.ts +3 -0
- package/dist/runtime/session-container.js +8 -0
- package/dist/runtime/session-container.js.map +1 -1
- package/dist/runtime/session-launcher.d.ts +2 -1
- package/dist/runtime/session-launcher.js +4 -1
- package/dist/runtime/session-launcher.js.map +1 -1
- package/dist/store/file-session-store.js +1 -1
- package/dist/store/file-session-store.js.map +1 -1
- package/dist/store/file-session-stream-provider.d.ts +1 -0
- package/dist/store/file-session-stream-provider.js +13 -13
- package/dist/store/file-session-stream-provider.js.map +1 -1
- package/dist/store/fix-session-store-factory.d.ts +1 -1
- package/dist/store/fix-session-store-factory.js.map +1 -1
- package/dist/store/fix-session-store.d.ts +11 -11
- package/dist/store/fix-session-store.js.map +1 -1
- package/dist/store/memory-session-store.js.map +1 -1
- package/dist/store/session-stream-provider.d.ts +13 -13
- package/dist/store/session-stream-provider.js.map +1 -1
- package/dist/transport/ascii/ascii-msg-transmitter.d.ts +1 -0
- package/dist/transport/ascii/ascii-msg-transmitter.js +15 -0
- package/dist/transport/ascii/ascii-msg-transmitter.js.map +1 -1
- package/dist/transport/ascii/ascii-session-msg-factory.js +1 -7
- package/dist/transport/ascii/ascii-session-msg-factory.js.map +1 -1
- package/dist/transport/fixml/fixml-session-msg-factory.js +1 -6
- package/dist/transport/fixml/fixml-session-msg-factory.js.map +1 -1
- package/dist/transport/index.d.ts +3 -0
- package/dist/transport/index.js +3 -0
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/msg-payload.d.ts +3 -1
- package/dist/transport/msg-payload.js +2 -1
- package/dist/transport/msg-payload.js.map +1 -1
- package/dist/transport/msg-transmitter.d.ts +4 -1
- package/dist/transport/msg-transmitter.js +18 -2
- package/dist/transport/msg-transmitter.js.map +1 -1
- package/dist/transport/send-callback.d.ts +7 -0
- package/dist/transport/send-callback.js +3 -0
- package/dist/transport/send-callback.js.map +1 -0
- package/dist/transport/session/fix-clock.d.ts +1 -1
- package/dist/transport/session/fix-clock.js.map +1 -1
- package/dist/transport/session/fix-session.d.ts +2 -1
- package/dist/transport/session/fix-session.js +12 -3
- package/dist/transport/session/fix-session.js.map +1 -1
- package/dist/transport/session/resend-request-manager.d.ts +2 -2
- package/dist/transport/session/resend-request-manager.js.map +1 -1
- package/dist/transport/session/session-description.d.ts +2 -0
- package/dist/transport/session/session-description.js.map +1 -1
- package/dist/transport/session/session-sequence-coordinator.d.ts +1 -1
- package/dist/transport/session/session-sequence-coordinator.js.map +1 -1
- package/dist/transport/session/session-sequence-store.d.ts +3 -3
- package/dist/transport/session/session-sequence-store.js.map +1 -1
- package/dist/transport/tcp/tcp-initiator.js.map +1 -1
- package/docs/benchmarking.md +117 -0
- package/docs/custom-logon.md +225 -0
- package/eslint.config.mjs +15 -1
- package/jsfix.test_client.txt +62 -62
- package/jsfix.test_server.txt +72 -72
- package/package.json +9 -1
- package/src/benchmark/bench-report.ts +101 -0
- package/src/benchmark/bench-runner.ts +196 -0
- package/src/benchmark/bench-stats.ts +86 -0
- package/src/benchmark/bench-types.ts +110 -0
- package/src/benchmark/gc-probe.ts +145 -0
- package/src/benchmark/index.ts +6 -0
- package/src/benchmark/parse-bench.ts +144 -0
- package/src/buffer/ascii/ascii-encoder.ts +20 -0
- package/src/buffer/ascii/ascii-parser.ts +16 -1
- package/src/buffer/ascii/ascii-segment-parser.ts +9 -6
- package/src/buffer/ascii/tag-index.ts +3 -3
- package/src/buffer/msg-encoder.ts +12 -0
- package/src/buffer/msg-view.ts +35 -18
- package/src/dictionary/parser/quickfix/dictionary-validator.ts +1 -1
- package/src/dictionary/parser/quickfix/quick-fix-graph-parser.ts +2 -3
- package/src/dictionary/parser/quickfix/validation-error.ts +1 -1
- package/src/jsfix-bench.ts +204 -0
- package/src/runtime/session-container.ts +20 -0
- package/src/runtime/session-launcher.ts +19 -2
- package/src/store/file-session-store.ts +2 -2
- package/src/store/file-session-stream-provider.ts +17 -11
- package/src/store/fix-session-store-factory.ts +1 -1
- package/src/store/fix-session-store.ts +11 -11
- package/src/store/memory-session-store.ts +1 -1
- package/src/store/session-stream-provider.ts +13 -13
- package/src/transport/ascii/ascii-msg-transmitter.ts +20 -0
- package/src/transport/ascii/ascii-session-msg-factory.ts +6 -1
- package/src/transport/fixml/fixml-session-msg-factory.ts +3 -1
- package/src/transport/index.ts +5 -0
- package/src/transport/msg-payload.ts +5 -1
- package/src/transport/msg-transmitter.ts +31 -2
- package/src/transport/send-callback.ts +33 -0
- package/src/transport/session/fix-clock.ts +1 -1
- package/src/transport/session/fix-session.ts +22 -3
- package/src/transport/session/resend-request-manager.ts +4 -4
- package/src/transport/session/session-description.ts +14 -0
- package/src/transport/session/session-sequence-coordinator.ts +1 -1
- package/src/transport/session/session-sequence-store.ts +3 -3
- package/src/transport/tcp/tcp-initiator.ts +1 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export interface IBenchCase {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly description?: string;
|
|
4
|
+
setup?: () => void;
|
|
5
|
+
run: (operations: number) => number;
|
|
6
|
+
teardown?: () => void;
|
|
7
|
+
}
|
|
8
|
+
export interface IBenchOptions {
|
|
9
|
+
readonly warmupOperations: number;
|
|
10
|
+
readonly rounds: number;
|
|
11
|
+
readonly operationsPerRound: number;
|
|
12
|
+
readonly gcBetweenRounds: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface ISampleStats {
|
|
15
|
+
readonly samples: number;
|
|
16
|
+
readonly min: number;
|
|
17
|
+
readonly max: number;
|
|
18
|
+
readonly mean: number;
|
|
19
|
+
readonly median: number;
|
|
20
|
+
readonly p95: number;
|
|
21
|
+
readonly p99: number;
|
|
22
|
+
readonly stdDev: number;
|
|
23
|
+
readonly coefficientOfVariation: number;
|
|
24
|
+
}
|
|
25
|
+
export interface IGcTotals {
|
|
26
|
+
readonly minor: number;
|
|
27
|
+
readonly major: number;
|
|
28
|
+
readonly incremental: number;
|
|
29
|
+
readonly weakCallback: number;
|
|
30
|
+
readonly total: number;
|
|
31
|
+
readonly totalPauseMs: number;
|
|
32
|
+
readonly longestPauseMs: number;
|
|
33
|
+
}
|
|
34
|
+
export interface IMemoryResult {
|
|
35
|
+
readonly operations: number;
|
|
36
|
+
readonly retainedHeapBytes: number;
|
|
37
|
+
readonly retainedBytesPerOperation: number;
|
|
38
|
+
readonly heapAtEndOfPassBytes: number;
|
|
39
|
+
readonly gc: IGcTotals;
|
|
40
|
+
readonly minorGcPerMillionOperations: number;
|
|
41
|
+
readonly majorGcPerMillionOperations: number;
|
|
42
|
+
readonly gcPauseMsPerMillionOperations: number;
|
|
43
|
+
readonly forcedGcAvailable: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface IRoundResult {
|
|
46
|
+
readonly round: number;
|
|
47
|
+
readonly operations: number;
|
|
48
|
+
readonly elapsedNanos: number;
|
|
49
|
+
readonly nanosPerOperation: number;
|
|
50
|
+
}
|
|
51
|
+
export interface IEnvironment {
|
|
52
|
+
readonly node: string;
|
|
53
|
+
readonly v8: string;
|
|
54
|
+
readonly platform: string;
|
|
55
|
+
readonly arch: string;
|
|
56
|
+
readonly cpu: string;
|
|
57
|
+
readonly cpuCount: number;
|
|
58
|
+
readonly forcedGcAvailable: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface IBenchResult {
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly description?: string;
|
|
63
|
+
readonly options: IBenchOptions;
|
|
64
|
+
readonly rounds: IRoundResult[];
|
|
65
|
+
readonly timing: ISampleStats;
|
|
66
|
+
readonly operationsPerSecond: number;
|
|
67
|
+
readonly memory: IMemoryResult;
|
|
68
|
+
}
|
|
69
|
+
export interface IBenchSuiteResult {
|
|
70
|
+
readonly label: string;
|
|
71
|
+
readonly capturedAt: string;
|
|
72
|
+
readonly environment: IEnvironment;
|
|
73
|
+
readonly results: IBenchResult[];
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bench-types.js","sourceRoot":"","sources":["../../src/benchmark/bench-types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * A unit of work the runner can drive. run is handed the number of operations\n * to perform and returns how many it actually completed, which the runner\n * checks - a case that silently does less work than asked would otherwise look\n * like a large improvement.\n */\nexport interface IBenchCase {\n readonly name: string\n readonly description?: string\n /** called once before warmup, outside all timing */\n setup?: () => void\n run: (operations: number) => number\n teardown?: () => void\n}\n\nexport interface IBenchOptions {\n /** operations run and discarded before measuring, to let v8 tier the code up */\n readonly warmupOperations: number\n /** measured rounds - each contributes one sample */\n readonly rounds: number\n readonly operationsPerRound: number\n /** collect between rounds so one round's garbage is not charged to the next */\n readonly gcBetweenRounds: boolean\n}\n\nexport interface ISampleStats {\n readonly samples: number\n readonly min: number\n readonly max: number\n readonly mean: number\n readonly median: number\n readonly p95: number\n readonly p99: number\n readonly stdDev: number\n /** stdDev as a fraction of the mean - the run to run noise floor */\n readonly coefficientOfVariation: number\n}\n\nexport interface IGcTotals {\n readonly minor: number\n readonly major: number\n readonly incremental: number\n readonly weakCallback: number\n readonly total: number\n readonly totalPauseMs: number\n readonly longestPauseMs: number\n}\n\nexport interface IMemoryResult {\n /** operations in the diagnostics pass these figures were taken over */\n readonly operations: number\n /**\n * heapUsed after a forced collection, less the same reading taken before the\n * measured rounds - what the work left behind rather than what it churned\n */\n readonly retainedHeapBytes: number\n readonly retainedBytesPerOperation: number\n /**\n * heapUsed sampled the instant the pass finished. Not a high water mark -\n * it is wherever the sawtooth happened to be - so read it as a rough sense of\n * the working set, not as a peak.\n */\n readonly heapAtEndOfPassBytes: number\n readonly gc: IGcTotals\n /**\n * collections per million operations. allocation volume is not directly\n * observable from node, so this is the comparable proxy for it - the same\n * work triggering fewer scavenges is the same work allocating less.\n */\n readonly minorGcPerMillionOperations: number\n readonly majorGcPerMillionOperations: number\n readonly gcPauseMsPerMillionOperations: number\n /** false when the process was started without --expose-gc */\n readonly forcedGcAvailable: boolean\n}\n\nexport interface IRoundResult {\n readonly round: number\n readonly operations: number\n readonly elapsedNanos: number\n readonly nanosPerOperation: number\n}\n\nexport interface IEnvironment {\n readonly node: string\n readonly v8: string\n readonly platform: string\n readonly arch: string\n readonly cpu: string\n readonly cpuCount: number\n readonly forcedGcAvailable: boolean\n}\n\nexport interface IBenchResult {\n readonly name: string\n readonly description?: string\n readonly options: IBenchOptions\n readonly rounds: IRoundResult[]\n /** statistics over the per round nanosPerOperation samples */\n readonly timing: ISampleStats\n readonly operationsPerSecond: number\n readonly memory: IMemoryResult\n}\n\nexport interface IBenchSuiteResult {\n readonly label: string\n readonly capturedAt: string\n readonly environment: IEnvironment\n readonly results: IBenchResult[]\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IGcTotals } from './bench-types';
|
|
2
|
+
export declare class GcProbe {
|
|
3
|
+
private observer;
|
|
4
|
+
private minor;
|
|
5
|
+
private major;
|
|
6
|
+
private incremental;
|
|
7
|
+
private weakCallback;
|
|
8
|
+
private totalPauseMs;
|
|
9
|
+
private longestPauseMs;
|
|
10
|
+
static forcedGcAvailable(): boolean;
|
|
11
|
+
static forceGc(): void;
|
|
12
|
+
seen(): number;
|
|
13
|
+
start(): void;
|
|
14
|
+
stop(): IGcTotals;
|
|
15
|
+
private reset;
|
|
16
|
+
private record;
|
|
17
|
+
private totals;
|
|
18
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GcProbe = void 0;
|
|
4
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
5
|
+
const emptyTotals = {
|
|
6
|
+
minor: 0,
|
|
7
|
+
major: 0,
|
|
8
|
+
incremental: 0,
|
|
9
|
+
weakCallback: 0,
|
|
10
|
+
total: 0,
|
|
11
|
+
totalPauseMs: 0,
|
|
12
|
+
longestPauseMs: 0
|
|
13
|
+
};
|
|
14
|
+
class GcProbe {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.observer = null;
|
|
17
|
+
this.minor = 0;
|
|
18
|
+
this.major = 0;
|
|
19
|
+
this.incremental = 0;
|
|
20
|
+
this.weakCallback = 0;
|
|
21
|
+
this.totalPauseMs = 0;
|
|
22
|
+
this.longestPauseMs = 0;
|
|
23
|
+
}
|
|
24
|
+
static forcedGcAvailable() {
|
|
25
|
+
return typeof global.gc === 'function';
|
|
26
|
+
}
|
|
27
|
+
static forceGc() {
|
|
28
|
+
const gc = global.gc;
|
|
29
|
+
if (typeof gc !== 'function')
|
|
30
|
+
return;
|
|
31
|
+
gc();
|
|
32
|
+
gc();
|
|
33
|
+
}
|
|
34
|
+
seen() {
|
|
35
|
+
return this.minor + this.major + this.incremental + this.weakCallback;
|
|
36
|
+
}
|
|
37
|
+
start() {
|
|
38
|
+
this.reset();
|
|
39
|
+
const observer = new perf_hooks_1.PerformanceObserver((list) => {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
for (const entry of list.getEntries()) {
|
|
42
|
+
const gcEntry = entry;
|
|
43
|
+
this.record(gcEntry.duration, (_b = (_a = gcEntry.detail) === null || _a === void 0 ? void 0 : _a.kind) !== null && _b !== void 0 ? _b : 0);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
observer.observe({ entryTypes: ['gc'], buffered: true });
|
|
47
|
+
this.observer = observer;
|
|
48
|
+
}
|
|
49
|
+
stop() {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
const observer = this.observer;
|
|
52
|
+
if (!observer)
|
|
53
|
+
return emptyTotals;
|
|
54
|
+
for (const entry of observer.takeRecords()) {
|
|
55
|
+
const gcEntry = entry;
|
|
56
|
+
this.record(gcEntry.duration, (_b = (_a = gcEntry.detail) === null || _a === void 0 ? void 0 : _a.kind) !== null && _b !== void 0 ? _b : 0);
|
|
57
|
+
}
|
|
58
|
+
observer.disconnect();
|
|
59
|
+
this.observer = null;
|
|
60
|
+
return this.totals();
|
|
61
|
+
}
|
|
62
|
+
reset() {
|
|
63
|
+
this.minor = 0;
|
|
64
|
+
this.major = 0;
|
|
65
|
+
this.incremental = 0;
|
|
66
|
+
this.weakCallback = 0;
|
|
67
|
+
this.totalPauseMs = 0;
|
|
68
|
+
this.longestPauseMs = 0;
|
|
69
|
+
}
|
|
70
|
+
record(durationMs, kind) {
|
|
71
|
+
this.totalPauseMs += durationMs;
|
|
72
|
+
this.longestPauseMs = Math.max(this.longestPauseMs, durationMs);
|
|
73
|
+
switch (kind) {
|
|
74
|
+
case perf_hooks_1.constants.NODE_PERFORMANCE_GC_MINOR:
|
|
75
|
+
++this.minor;
|
|
76
|
+
break;
|
|
77
|
+
case perf_hooks_1.constants.NODE_PERFORMANCE_GC_MAJOR:
|
|
78
|
+
++this.major;
|
|
79
|
+
break;
|
|
80
|
+
case perf_hooks_1.constants.NODE_PERFORMANCE_GC_INCREMENTAL:
|
|
81
|
+
++this.incremental;
|
|
82
|
+
break;
|
|
83
|
+
case perf_hooks_1.constants.NODE_PERFORMANCE_GC_WEAKCB:
|
|
84
|
+
++this.weakCallback;
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
totals() {
|
|
91
|
+
return {
|
|
92
|
+
minor: this.minor,
|
|
93
|
+
major: this.major,
|
|
94
|
+
incremental: this.incremental,
|
|
95
|
+
weakCallback: this.weakCallback,
|
|
96
|
+
total: this.minor + this.major + this.incremental + this.weakCallback,
|
|
97
|
+
totalPauseMs: this.totalPauseMs,
|
|
98
|
+
longestPauseMs: this.longestPauseMs
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.GcProbe = GcProbe;
|
|
103
|
+
//# sourceMappingURL=gc-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gc-probe.js","sourceRoot":"","sources":["../../src/benchmark/gc-probe.ts"],"names":[],"mappings":"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","sourcesContent":["import { PerformanceObserver, constants } from 'perf_hooks'\nimport { IGcTotals } from './bench-types'\n\ninterface IGcDetail {\n kind: number\n flags: number\n}\n\n/**\n * a gc performance entry. detail is not on the PerformanceEntry the node types\n * describe, it is only present on entries of this type\n */\ninterface IGcEntry {\n duration: number\n detail?: IGcDetail\n}\n\nconst emptyTotals: IGcTotals = {\n minor: 0,\n major: 0,\n incremental: 0,\n weakCallback: 0,\n total: 0,\n totalPauseMs: 0,\n longestPauseMs: 0\n}\n\n/**\n * Counts collections and the pause they cost while a benchmark runs.\n *\n * Node does not expose how many bytes a stretch of code allocated, so the\n * number of scavenges is the practical stand in - the same work provoking\n * fewer minor collections is the same work producing less garbage, and that\n * is the number worth moving for a drop copy engine where the cost of\n * allocation is felt as pause rather than as throughput.\n */\nexport class GcProbe {\n private observer: PerformanceObserver | null = null\n private minor: number = 0\n private major: number = 0\n private incremental: number = 0\n private weakCallback: number = 0\n private totalPauseMs: number = 0\n private longestPauseMs: number = 0\n\n /** whether the process was started with --expose-gc */\n public static forcedGcAvailable (): boolean {\n return typeof global.gc === 'function'\n }\n\n /**\n * Collect until the heap settles, so a reading taken afterwards reflects what\n * is genuinely retained. Two passes because the first can promote survivors\n * into the old space that the second is then able to reclaim. A no-op without\n * --expose-gc, in which case retained figures are indicative only.\n */\n public static forceGc (): void {\n const gc = global.gc\n if (typeof gc !== 'function') return\n gc()\n gc()\n }\n\n /** entries recorded so far - lets a caller wait for delivery to go quiet */\n public seen (): number {\n return this.minor + this.major + this.incremental + this.weakCallback\n }\n\n public start (): void {\n this.reset()\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n const gcEntry = entry as unknown as IGcEntry\n this.record(gcEntry.duration, gcEntry.detail?.kind ?? 0)\n }\n })\n // buffered so collections are not missed while the loop is busy - the\n // callback cannot run until the measured work yields\n observer.observe({ entryTypes: ['gc'], buffered: true })\n this.observer = observer\n }\n\n /**\n * Stop observing and return what was seen. Any entries still queued are\n * drained first - the observer callback is a macrotask and the benchmark\n * loop never yields, so without this every collection would be lost.\n */\n public stop (): IGcTotals {\n const observer = this.observer\n if (!observer) return emptyTotals\n for (const entry of observer.takeRecords()) {\n const gcEntry = entry as unknown as IGcEntry\n this.record(gcEntry.duration, gcEntry.detail?.kind ?? 0)\n }\n observer.disconnect()\n this.observer = null\n return this.totals()\n }\n\n private reset (): void {\n this.minor = 0\n this.major = 0\n this.incremental = 0\n this.weakCallback = 0\n this.totalPauseMs = 0\n this.longestPauseMs = 0\n }\n\n private record (durationMs: number, kind: number): void {\n this.totalPauseMs += durationMs\n this.longestPauseMs = Math.max(this.longestPauseMs, durationMs)\n switch (kind) {\n case constants.NODE_PERFORMANCE_GC_MINOR:\n ++this.minor\n break\n\n case constants.NODE_PERFORMANCE_GC_MAJOR:\n ++this.major\n break\n\n case constants.NODE_PERFORMANCE_GC_INCREMENTAL:\n ++this.incremental\n break\n\n case constants.NODE_PERFORMANCE_GC_WEAKCB:\n ++this.weakCallback\n break\n\n default:\n break\n }\n }\n\n private totals (): IGcTotals {\n return {\n minor: this.minor,\n major: this.major,\n incremental: this.incremental,\n weakCallback: this.weakCallback,\n total: this.minor + this.major + this.incremental + this.weakCallback,\n totalPauseMs: this.totalPauseMs,\n longestPauseMs: this.longestPauseMs\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./bench-types"), exports);
|
|
18
|
+
__exportStar(require("./bench-stats"), exports);
|
|
19
|
+
__exportStar(require("./bench-runner"), exports);
|
|
20
|
+
__exportStar(require("./bench-report"), exports);
|
|
21
|
+
__exportStar(require("./gc-probe"), exports);
|
|
22
|
+
__exportStar(require("./parse-bench"), exports);
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/benchmark/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B;AAC7B,gDAA6B;AAC7B,iDAA8B;AAC9B,iDAA8B;AAC9B,6CAA0B;AAC1B,gDAA6B","sourcesContent":["export * from './bench-types'\nexport * from './bench-stats'\nexport * from './bench-runner'\nexport * from './bench-report'\nexport * from './gc-probe'\nexport * from './parse-bench'\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { IJsFixConfig } from '../config/js-fix-config';
|
|
2
|
+
import { IBenchCase } from './bench-types';
|
|
3
|
+
export declare enum ParseDepth {
|
|
4
|
+
View = "view",
|
|
5
|
+
Object = "object"
|
|
6
|
+
}
|
|
7
|
+
export interface IParseCaseOptions {
|
|
8
|
+
readonly config: IJsFixConfig;
|
|
9
|
+
readonly contents: string;
|
|
10
|
+
readonly depth: ParseDepth;
|
|
11
|
+
}
|
|
12
|
+
export declare class ParseCase implements IBenchCase {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly description: string;
|
|
15
|
+
readonly operationsPerInvocation: number;
|
|
16
|
+
private readonly source;
|
|
17
|
+
private readonly depth;
|
|
18
|
+
private readonly options;
|
|
19
|
+
private parser;
|
|
20
|
+
private decoded;
|
|
21
|
+
constructor(name: string, options: IParseCaseOptions);
|
|
22
|
+
alignOperations(requested: number): number;
|
|
23
|
+
setup(): void;
|
|
24
|
+
teardown(): void;
|
|
25
|
+
run(operations: number): number;
|
|
26
|
+
private makeParser;
|
|
27
|
+
private countMessages;
|
|
28
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ParseCase = exports.ParseDepth = void 0;
|
|
4
|
+
const ascii_parser_1 = require("../buffer/ascii/ascii-parser");
|
|
5
|
+
const di_tokens_1 = require("../runtime/di-tokens");
|
|
6
|
+
const session_scope_1 = require("../runtime/session-scope");
|
|
7
|
+
var ParseDepth;
|
|
8
|
+
(function (ParseDepth) {
|
|
9
|
+
ParseDepth["View"] = "view";
|
|
10
|
+
ParseDepth["Object"] = "object";
|
|
11
|
+
})(ParseDepth || (exports.ParseDepth = ParseDepth = {}));
|
|
12
|
+
class ParseCase {
|
|
13
|
+
constructor(name, options) {
|
|
14
|
+
this.parser = null;
|
|
15
|
+
this.decoded = 0;
|
|
16
|
+
this.name = name;
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.depth = options.depth;
|
|
19
|
+
this.source = Buffer.from(options.contents);
|
|
20
|
+
this.description = options.depth === ParseDepth.Object
|
|
21
|
+
? 'tokenise, discover structure, build view, materialise object'
|
|
22
|
+
: 'tokenise, discover structure, build view';
|
|
23
|
+
this.operationsPerInvocation = this.countMessages();
|
|
24
|
+
if (this.operationsPerInvocation === 0) {
|
|
25
|
+
throw new Error(`${name}: input yielded no messages, check the dictionary and the delimiter`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
alignOperations(requested) {
|
|
29
|
+
const per = this.operationsPerInvocation;
|
|
30
|
+
return Math.max(per, Math.ceil(requested / per) * per);
|
|
31
|
+
}
|
|
32
|
+
setup() {
|
|
33
|
+
this.parser = this.makeParser(true);
|
|
34
|
+
}
|
|
35
|
+
teardown() {
|
|
36
|
+
var _a;
|
|
37
|
+
(_a = this.parser) === null || _a === void 0 ? void 0 : _a.removeAllListeners();
|
|
38
|
+
this.parser = null;
|
|
39
|
+
}
|
|
40
|
+
run(operations) {
|
|
41
|
+
const parser = this.parser;
|
|
42
|
+
if (!parser) {
|
|
43
|
+
throw new Error(`${this.name}: run called before setup`);
|
|
44
|
+
}
|
|
45
|
+
const source = this.source;
|
|
46
|
+
const passes = operations / this.operationsPerInvocation;
|
|
47
|
+
if (!Number.isInteger(passes)) {
|
|
48
|
+
throw new Error(`${this.name}: ${operations} operations is not a whole number of passes over the input`);
|
|
49
|
+
}
|
|
50
|
+
this.decoded = 0;
|
|
51
|
+
for (let i = 0; i < passes; ++i) {
|
|
52
|
+
parser.parseBuffer(source);
|
|
53
|
+
}
|
|
54
|
+
return this.decoded;
|
|
55
|
+
}
|
|
56
|
+
makeParser(subscribe) {
|
|
57
|
+
const scoped = (0, session_scope_1.makeSessionScope)(this.options.config);
|
|
58
|
+
const container = scoped.sessionContainer;
|
|
59
|
+
const buffer = container.resolve(di_tokens_1.DITokens.ParseBuffer);
|
|
60
|
+
const maxMessageLen = container.resolve(di_tokens_1.DITokens.maxMessageLen);
|
|
61
|
+
const parser = new ascii_parser_1.AsciiParser(scoped, null, buffer, maxMessageLen);
|
|
62
|
+
const object = subscribe && this.depth === ParseDepth.Object;
|
|
63
|
+
parser.on('msg', (_, view) => {
|
|
64
|
+
++this.decoded;
|
|
65
|
+
if (object) {
|
|
66
|
+
const materialised = view.toObject();
|
|
67
|
+
if (materialised === null) {
|
|
68
|
+
throw new Error('view produced no object');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return parser;
|
|
73
|
+
}
|
|
74
|
+
countMessages() {
|
|
75
|
+
const parser = this.makeParser(false);
|
|
76
|
+
this.decoded = 0;
|
|
77
|
+
parser.parseBuffer(this.source);
|
|
78
|
+
parser.removeAllListeners();
|
|
79
|
+
const count = this.decoded;
|
|
80
|
+
this.decoded = 0;
|
|
81
|
+
return count;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.ParseCase = ParseCase;
|
|
85
|
+
//# sourceMappingURL=parse-bench.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-bench.js","sourceRoot":"","sources":["../../src/benchmark/parse-bench.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsciiParser } from '../buffer/ascii/ascii-parser'\nimport { ElasticBuffer } from '../buffer/elastic-buffer'\nimport { MsgView } from '../buffer/msg-view'\nimport { IJsFixConfig } from '../config/js-fix-config'\nimport { DITokens } from '../runtime/di-tokens'\nimport { makeSessionScope } from '../runtime/session-scope'\nimport { IBenchCase } from './bench-types'\n\n/**\n * what a decoded message is taken through once the parser has produced a view\n */\nexport enum ParseDepth {\n /** stop at the MsgView - tokenise, discover the structure, build the view */\n View = 'view',\n /** materialise the whole object graph, which is what most consumers do */\n Object = 'object'\n}\n\nexport interface IParseCaseOptions {\n readonly config: IJsFixConfig\n /** the raw text of a fix log, one or more complete messages */\n readonly contents: string\n readonly depth: ParseDepth\n}\n\n/**\n * Drives fix bytes through the real parser and counts messages out of it.\n *\n * The bytes are fed as one buffer per invocation, the same way a socket read\n * reaches parse, rather than by concatenating the file thousands of times into\n * one enormous string. That concatenation is itself a large allocation, and\n * doing it before the timer starts leaves a heap that no memory reading taken\n * afterwards can be trusted through.\n */\nexport class ParseCase implements IBenchCase {\n public readonly name: string\n public readonly description: string\n /** messages produced by one pass over the input */\n public readonly operationsPerInvocation: number\n\n private readonly source: Buffer\n private readonly depth: ParseDepth\n private readonly options: IParseCaseOptions\n private parser: AsciiParser | null = null\n private decoded: number = 0\n\n constructor (name: string, options: IParseCaseOptions) {\n this.name = name\n this.options = options\n this.depth = options.depth\n this.source = Buffer.from(options.contents)\n this.description = options.depth === ParseDepth.Object\n ? 'tokenise, discover structure, build view, materialise object'\n : 'tokenise, discover structure, build view'\n this.operationsPerInvocation = this.countMessages()\n if (this.operationsPerInvocation === 0) {\n throw new Error(`${name}: input yielded no messages, check the dictionary and the delimiter`)\n }\n }\n\n /**\n * Round a requested round size up to a whole number of passes over the input.\n * A pass cannot be stopped part way, so asking for a count that is not a\n * multiple of it would silently measure more work than it reported.\n */\n public alignOperations (requested: number): number {\n const per = this.operationsPerInvocation\n return Math.max(per, Math.ceil(requested / per) * per)\n }\n\n public setup (): void {\n this.parser = this.makeParser(true)\n }\n\n public teardown (): void {\n this.parser?.removeAllListeners()\n this.parser = null\n }\n\n public run (operations: number): number {\n const parser = this.parser\n if (!parser) {\n throw new Error(`${this.name}: run called before setup`)\n }\n const source = this.source\n const passes = operations / this.operationsPerInvocation\n if (!Number.isInteger(passes)) {\n throw new Error(`${this.name}: ${operations} operations is not a whole number of passes over the input`)\n }\n this.decoded = 0\n for (let i = 0; i < passes; ++i) {\n parser.parseBuffer(source)\n }\n return this.decoded\n }\n\n /**\n * A parser on a session scope of its own.\n *\n * It has to be a scope rather than a hand built AsciiParser: AsciiParserState\n * takes the ParseBuffer from the container, so a parser handed some other\n * buffer writes bytes the state never reads and the parse walks off into\n * nonsense. The scope re-registers the buffer and hands the same instance to\n * both, which is the same thing an accepted connection gets.\n */\n private makeParser (subscribe: boolean): AsciiParser {\n const scoped = makeSessionScope(this.options.config)\n const container = scoped.sessionContainer\n // constructed rather than resolved: DITokens.readStream has no registration\n // outside a live transport, and there is no stream here - the harness hands\n // the parser its bytes. Everything else comes from the scope, so the buffer\n // below is the same instance AsciiParserState will be injected with.\n const buffer = container.resolve<ElasticBuffer>(DITokens.ParseBuffer)\n const maxMessageLen = container.resolve<number>(DITokens.maxMessageLen)\n const parser = new AsciiParser(scoped, null, buffer, maxMessageLen)\n const object = subscribe && this.depth === ParseDepth.Object\n parser.on('msg', (_: string, view: MsgView) => {\n ++this.decoded\n if (object) {\n // read the result back so the materialisation cannot be treated as\n // dead and folded away\n const materialised = view.toObject()\n if (materialised === null) {\n throw new Error('view produced no object')\n }\n }\n })\n return parser\n }\n\n /**\n * How many messages one pass over the input yields. Counted on a throwaway\n * parser during construction so the measured run never has to ask.\n */\n private countMessages (): number {\n const parser = this.makeParser(false)\n this.decoded = 0\n parser.parseBuffer(this.source)\n parser.removeAllListeners()\n const count = this.decoded\n this.decoded = 0\n return count\n }\n}\n"]}
|
|
@@ -22,6 +22,7 @@ export declare class AsciiEncoder extends MsgEncoder {
|
|
|
22
22
|
encodeSet(objectToEncode: ILooseObject, set: IContainedSet): void;
|
|
23
23
|
private encodeObject;
|
|
24
24
|
private getFields;
|
|
25
|
+
private static expectedMiss;
|
|
25
26
|
private encodeInstances;
|
|
26
27
|
private WriteTagEquals;
|
|
27
28
|
private writeDelimiter;
|
|
@@ -73,11 +73,26 @@ class AsciiEncoder extends msg_encoder_1.MsgEncoder {
|
|
|
73
73
|
if (field) {
|
|
74
74
|
a[j++] = field;
|
|
75
75
|
}
|
|
76
|
+
else if (this.onUnknownField && !AsciiEncoder.expectedMiss(set, current)) {
|
|
77
|
+
this.onUnknownField(current, set.name);
|
|
78
|
+
}
|
|
76
79
|
return a;
|
|
77
80
|
}, new Array(keys.length));
|
|
78
81
|
fields.sort((a, b) => a.position - b.position);
|
|
79
82
|
return fields;
|
|
80
83
|
}
|
|
84
|
+
static expectedMiss(set, name) {
|
|
85
|
+
var _a;
|
|
86
|
+
if (name === 'StandardHeader' || name === 'StandardTrailer') {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
for (const group of set.groups.values()) {
|
|
90
|
+
if (((_a = group.noOfField) === null || _a === void 0 ? void 0 : _a.name) === name) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
81
96
|
encodeInstances(o, gf) {
|
|
82
97
|
const noOfField = gf.definition.noOfField;
|
|
83
98
|
if (!noOfField)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ascii-encoder.js","sourceRoot":"","sources":["../../../src/buffer/ascii/ascii-encoder.ts"],"names":[],"mappings":";;;AACA,0DAImC;AAEnC,gDAA2C;AAE3C,qDAAgD;AAEhD,+CAA0C;AAC1C,sCAAkC;AAClC,8CAAyC;AAEzC,MAAa,YAAa,SAAQ,wBAAU;IAO1C,YAA6B,MAAqB,EAChC,WAA2B,EAC3B,gBAAgC,IAAI,8BAAa,CAAC,MAAM,CAAC,EACzD,YAAoB,wBAAU,CAAC,GAAG,EAClC,eAAuB,wBAAU,CAAC,IAAI;QACtD,KAAK,CAAC,WAAW,CAAC,CAAA;QALS,WAAM,GAAN,MAAM,CAAe;QAChC,gBAAW,GAAX,WAAW,CAAgB;QAC3B,kBAAa,GAAb,aAAa,CAA4C;QACzD,cAAS,GAAT,SAAS,CAAyB;QAClC,iBAAY,GAAZ,YAAY,CAA0B;QAPjD,gBAAW,GAAY,IAAI,CAAA;QACzB,eAAU,GAAmB,IAAI,0BAAc,EAAE,CAAA;QAQxD,IAAI,CAAC,IAAI,GAAG,IAAI,WAAI,EAAE,CAAA;IACxB,CAAC;IAEM,IAAI;QACT,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAA;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAA;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACtB,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;YAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC;gBACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;gBAC7B,CAAC,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;YACpD,CAAC;QACH,CAAC;QAED,OAAO,CAAC,CAAA;IACV,CAAC;IAIM,KAAK;QACV,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACnB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;IACnB,CAAC;IAEM,SAAS,CAAE,cAA4B,EAAE,GAAkB;QAChE,MAAM,OAAO,GAA0B,IAAI,qBAAqB,EAAE,CAAA;QAClE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IACjD,CAAC;IAEO,YAAY,CAAE,cAA4B,EAAE,GAAkB,EAAE,KAA4B;QAClG,MAAM,MAAM,GAAqB,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;QACpE,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,MAAM,EAAE;YACrC,MAAM,EAAE,CAAC,EAAwB,EAAE,EAAE;gBACnC,MAAM,GAAG,GAAQ,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;gBAExC,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;oBAC9B,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;wBACtB,KAAK,CAAC,WAAW,GAAG,EAAE,CAAA;oBACxB,CAAC;oBACD,KAAK,CAAC,UAAU,GAAG,EAAE,CAAA;oBACrB,KAAK,CAAC,KAAK,EAAE,CAAA;oBACb,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;gBACjD,CAAC;YACH,CAAC;YACD,SAAS,EAAE,CAAC,EAA2B,EAAE,EAAE;gBACzC,MAAM,QAAQ,GAAiB,cAAc,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;gBACjE,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;gBACnD,CAAC;YACH,CAAC;YACD,KAAK,EAAE,CAAC,EAAuB,EAAE,EAAE;gBACjC,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,CAAC,CAAA;YAC1C,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAEO,SAAS,CAAE,GAAkB,EAAE,CAAe;QACpD,MAAM,IAAI,GAAa,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACrC,IAAI,CAAC,GAAW,CAAC,CAAA;QACjB,MAAM,MAAM,GAAqB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAmB,EAAE,OAAe,EAAE,EAAE;YACpF,MAAM,KAAK,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YAC/C,IAAI,KAAK,EAAE,CAAC;gBACV,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAA;YAChB,CAAC;YACD,OAAO,CAAC,CAAA;QACV,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QAC1B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAiB,EAAE,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC9E,OAAO,MAAM,CAAA;IACf,CAAC;IAEO,eAAe,CAAE,CAAe,EAAE,EAAuB;QAC/D,MAAM,SAAS,GAAiC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAA;QACvE,IAAI,CAAC,SAAS;YAAE,OAAM;QACtB,MAAM,SAAS,GAAmB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QAEjE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,qCAAqC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAA;QACxE,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,IAAI,cAAc,CAAC,EAAE,CAAC,CAAA;YACxC,MAAM,IAAI,GAA0B,SAAS,CAAC,IAAI,CAAA;YAGlD,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;YAClC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;YACnC,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;YACzC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;YAC/C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC;gBACtD,MAAM,QAAQ,GAAiB,SAAS,CAAC,KAAK,CAAC,CAAA;gBAC/C,IAAI,CAAC,KAAK,EAAE,CAAA;gBACZ,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;gBAC3C,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;gBACnD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,SAAS,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAA;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAEO,cAAc,CAAE,GAAW;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,SAAS,CAAC,wBAAU,CAAC,KAAK,CAAC,CAAA;IACpC,CAAC;IAEO,cAAc,CAAE,WAAmB,EAAE,GAAW;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAA;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,WAAW,EAAE,GAAG,CAAC,CAAA;QAChE,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IAC7B,CAAC;IAEO,YAAY,CAAE,CAAe,EAAE,GAAkB,EAAE,EAAwB,EAAE,GAAQ;QAC3F,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAA;QAChC,MAAM,GAAG,GAAW,UAAU,CAAC,GAAG,CAAA;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAA;QACnC,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;QAC3B,IAAI,WAAW,GAAG,CAAC,CAAA;QAEnB,IAAI,OAAgB,CAAA;QACpB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,QAAQ,UAAU,CAAC,OAAO,EAAE,CAAC;gBAC3B,KAAK,kBAAO,CAAC,OAAO,CAAC,CAAC,CAAC;oBACrB,OAAO,GAAG,UAAU,CAAC,OAAO,CAAA;oBAC5B,MAAM,EAAE,GAAW,GAAG,CAAA;oBACtB,MAAM,KAAK,GAAW,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;oBACxD,GAAG,GAAG,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,CAAA;oBACpC,MAAK;gBACP,CAAC;gBACD,OAAO,CAAC,CAAC,CAAC;oBACR,OAAO,GAAG,kBAAO,CAAC,MAAM,CAAA;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,UAAU,CAAC,OAAO,CAAA;QAC9B,CAAC;QAED,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,kBAAO,CAAC,OAAO,CAAC,CAAC,CAAC;gBAErB,MAAK;YACP,CAAC;YAED,OAAO,CAAC,CAAC,CAAC;gBACR,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;gBACxB,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;gBAC7B,MAAK;YACP,CAAC;QACH,CAAC;QAED,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,kBAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBACpB,MAAM,CAAC,WAAW,CAAC,GAAa,CAAC,CAAA;gBACjC,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnB,MAAM,CAAC,WAAW,CAAC,GAAa,CAAC,CAAA;gBACjC,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,GAAG,CAAC;YACjB,KAAK,kBAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBACpB,MAAM,CAAC,gBAAgB,CAAC,GAAa,CAAC,CAAA;gBACtC,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,OAAO,CAAC,CAAC,CAAC;gBACrB,MAAM,CAAC,YAAY,CAAC,GAAc,CAAC,CAAA;gBACnC,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,YAAY,CAAC,CAAC,CAAC;gBAC1B,EAAE,CAAC,iBAAiB,CAAC,GAAW,CAAC,CAAA;gBACjC,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,WAAW,CAAC,CAAC,CAAC;gBACzB,EAAE,CAAC,YAAY,CAAC,GAAW,CAAC,CAAA;gBAC5B,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,WAAW,CAAC,CAAC,CAAC;gBACzB,EAAE,CAAC,YAAY,CAAC,GAAW,CAAC,CAAA;gBAC5B,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,SAAS,CAAC,CAAC,CAAC;gBACvB,EAAE,CAAC,cAAc,CAAC,GAAW,CAAC,CAAA;gBAC9B,MAAK;YACP,CAAC;YAED,KAAK,kBAAO,CAAC,OAAO,CAAC,CAAC,CAAC;gBACrB,MAAM,CAAC,GAAG,GAAa,CAAA;gBACvB,MAAM,QAAQ,GAAyB,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAyB,CAAA;gBAC1F,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;oBAC7B,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;oBAC5C,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;oBACjC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;gBAC7B,CAAC;gBACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;gBACxB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;gBACrB,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;gBAC7B,MAAK;YACP,CAAC;YAED,OAAO,CAAC,CAAC,CAAC;gBACR,MAAM,CAAC,WAAW,CAAC,GAAa,CAAC,CAAA;gBACjC,MAAK;YACP,CAAC;QACH,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;QAErC,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,WAAI,CAAC,aAAa;gBACrB,IAAI,CAAC,aAAa,GAAG,GAAG,GAAG,CAAC,CAAA;gBAC5B,MAAK;YAEP,KAAK,WAAI,CAAC,MAAM;gBACd,IAAI,CAAC,UAAU,GAAG,GAAG,CAAA;gBACrB,MAAK;QACT,CAAC;IACH,CAAC;CACF;AAjPD,oCAiPC;AAED,MAAM,cAAc;IAClB,YAA6B,EAAuB,EAClC,QAA+B,IAAI,qBAAqB,EAAE,EAC1D,OAA8B,IAAI,qBAAqB,EAAE;QAF9C,OAAE,GAAF,EAAE,CAAqB;QAClC,UAAK,GAAL,KAAK,CAAqD;QAC1D,SAAI,GAAJ,IAAI,CAAqD;IAC3E,CAAC;IAED,UAAU,CAAE,KAAa;QACvB,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7C,CAAC;IAED,mBAAmB,CAAE,KAAa;;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACtB,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,iDAAiD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;QAClF,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,8BAA8B,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;QACvF,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,MAAA,KAAK,CAAC,WAAW,0CAAE,UAAU,CAAC,GAAG,CAAA;YAClD,MAAM,GAAG,GAAG,MAAA,IAAI,CAAC,WAAW,0CAAE,UAAU,CAAC,GAAG,CAAA;YAC5C,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;gBACrB,MAAM,GAAG,GAAG,mBAAmB,KAAK,4BAA4B,GAAG,iBAAiB,QAAQ,EAAE,CAAA;gBAC9F,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,qBAAqB;IACzB,YAAoB,cAA2C,IAAI,EAC1D,aAA0C,IAAI,EAC9C,QAAgB,CAAC;QAFN,gBAAW,GAAX,WAAW,CAAoC;QAC1D,eAAU,GAAV,UAAU,CAAoC;QAC9C,UAAK,GAAL,KAAK,CAAY;IAC1B,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;QACvB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;IAChB,CAAC;IAEM,KAAK;QACV,OAAO,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,CAAA;IACtD,CAAC;CACF","sourcesContent":["import { ILooseObject } from '../../collections/collection'\nimport {\n ContainedGroupField, ContainedSimpleField,\n IContainedSet, ContainedField,\n ContainedComponentField, FieldsDispatch\n} from '../../dictionary/contained'\nimport { SimpleFieldDefinition, FixDefinitions } from '../../dictionary/definition'\nimport { MsgEncoder } from '../msg-encoder'\nimport { ElasticBuffer } from '../elastic-buffer'\nimport { TimeFormatter } from './time-formatter'\nimport { ITimeFormatter } from './itime-formatter'\nimport { AsciiChars } from './ascii-chars'\nimport { Tags } from '../tag/tags'\nimport { TagType } from '../tag/tag-type'\n\nexport class AsciiEncoder extends MsgEncoder {\n public bodyLengthPos: number\n public msgTypePos: number\n public tags: Tags\n public checkGroups: boolean = true\n readonly dispatcher: FieldsDispatch = new FieldsDispatch()\n\n constructor (public readonly buffer: ElasticBuffer,\n public readonly definitions: FixDefinitions,\n public readonly timeFormatter: ITimeFormatter = new TimeFormatter(buffer),\n public readonly delimiter: number = AsciiChars.Soh,\n public readonly logDelimiter: number = AsciiChars.Pipe) {\n super(definitions)\n this.tags = new Tags()\n }\n\n public trim (): Buffer {\n const b = this.buffer.copy()\n const delimiter = this.delimiter\n const logDelimiter = this.logDelimiter\n const tags = this.tags\n if (delimiter !== logDelimiter) {\n for (let p = 0; p < tags.nextTagPos; ++p) {\n const tagPos = tags.tagPos[p]\n b.writeUInt8(delimiter, tagPos.start + tagPos.len)\n }\n }\n\n return b\n }\n\n // only reset tags after entire message is encoded - <hdr>body<trl>\n\n public reset (): void {\n this.buffer.reset()\n this.tags.reset()\n }\n\n public encodeSet (objectToEncode: ILooseObject, set: IContainedSet): void {\n const summary: AsciiEncodeSetSummary = new AsciiEncodeSetSummary()\n this.encodeObject(objectToEncode, set, summary)\n }\n\n private encodeObject (objectToEncode: ILooseObject, set: IContainedSet, state: AsciiEncodeSetSummary): void {\n const fields: ContainedField[] = this.getFields(set, objectToEncode)\n this.dispatcher.dispatchFields(fields, {\n simple: (sf: ContainedSimpleField) => {\n const val: any = objectToEncode[sf.name]\n // Empty strings are omitted as they result in empty values for tags, which are considered malformed.\n if (val != null && val !== '') {\n if (state.count === 0) {\n state.firstSimple = sf\n }\n state.lastSimple = sf\n state.count++\n this.encodeSimple(objectToEncode, set, sf, val)\n }\n },\n component: (cf: ContainedComponentField) => {\n const instance: ILooseObject = objectToEncode[cf.definition.name]\n if (instance) {\n this.encodeObject(instance, cf.definition, state)\n }\n },\n group: (gf: ContainedGroupField) => {\n this.encodeInstances(objectToEncode, gf)\n }\n })\n }\n\n private getFields (set: IContainedSet, o: ILooseObject): ContainedField[] {\n const keys: string[] = Object.keys(o)\n let j: number = 0\n const fields: ContainedField[] = keys.reduce((a: ContainedField[], current: string) => {\n const field = set.localNameToField.get(current)\n if (field) {\n a[j++] = field\n }\n return a\n }, new Array(keys.length))\n fields.sort((a: ContainedField, b: ContainedField) => a.position - b.position)\n return fields\n }\n\n private encodeInstances (o: ILooseObject, gf: ContainedGroupField): void {\n const noOfField: SimpleFieldDefinition | null = gf.definition.noOfField\n if (!noOfField) return\n const instances: ILooseObject[] = o[gf.name] || o[noOfField.name]\n\n const buffer = this.buffer\n if (!Array.isArray(instances)) {\n throw new Error(`expected array instance for group ${noOfField.name}`)\n }\n if (instances) {\n const validator = new GroupValidator(gf)\n const test: AsciiEncodeSetSummary = validator.test\n\n // a repeated group has number of instances at the start of group\n this.WriteTagEquals(noOfField.tag)\n const posValBegin = buffer.getPos()\n buffer.writeWholeNumber(instances.length)\n this.writeDelimiter(posValBegin, noOfField.tag)\n for (let field = 0; field < instances.length; ++field) {\n const instance: ILooseObject = instances[field]\n test.reset()\n const summary = validator.getSummary(field)\n this.encodeObject(instance, gf.definition, summary)\n if (this.checkGroups) {\n validator.assertInstanceValid(field)\n }\n }\n }\n }\n\n private WriteTagEquals (tag: number): void {\n const buffer = this.buffer\n buffer.writeWholeNumber(tag)\n buffer.writeChar(AsciiChars.Equal)\n }\n\n private writeDelimiter (posValBegin: number, tag: number): void {\n const delimiter = this.logDelimiter\n const buffer = this.buffer\n this.tags.store(posValBegin, buffer.getPos() - posValBegin, tag)\n buffer.writeChar(delimiter)\n }\n\n private encodeSimple (o: ILooseObject, set: IContainedSet, sf: ContainedSimpleField, val: any): void {\n const definition = sf.definition\n const tag: number = definition.tag\n const buffer = this.buffer\n const delimiter = this.logDelimiter\n const tf = this.timeFormatter\n const pos = buffer.getPos()\n let posValBegin = 0\n\n let tagType: TagType\n if (typeof val === 'string') {\n switch (definition.tagType) {\n case TagType.Boolean: {\n tagType = definition.tagType\n const vs: string = val\n const first: string = vs.length > 0 ? vs.charAt(0) : 'N'\n val = first === 'Y' || first === 'T'\n break\n }\n default: {\n tagType = TagType.String\n }\n }\n } else {\n tagType = definition.tagType\n }\n\n switch (tagType) {\n case TagType.RawData: {\n // may need to first write raw message length (see below)\n break\n }\n\n default: {\n this.WriteTagEquals(tag)\n posValBegin = buffer.getPos()\n break\n }\n }\n\n switch (tagType) {\n case TagType.String: {\n buffer.writeString(val as string)\n break\n }\n\n case TagType.Float: {\n buffer.writeNumber(val as number)\n break\n }\n\n case TagType.Int:\n case TagType.Length: {\n buffer.writeWholeNumber(val as number)\n break\n }\n\n case TagType.Boolean: {\n buffer.writeBoolean(val as boolean)\n break\n }\n\n case TagType.UtcTimestamp: {\n tf.writeUtcTimestamp(val as Date)\n break\n }\n\n case TagType.UtcTimeOnly: {\n tf.writeUtcTime(val as Date)\n break\n }\n\n case TagType.UtcDateOnly: {\n tf.writeUtcDate(val as Date)\n break\n }\n\n case TagType.LocalDate: {\n tf.writeLocalDate(val as Date)\n break\n }\n\n case TagType.RawData: {\n const b = val as Buffer\n const lenField: ContainedSimpleField = set.fields[sf.position - 1] as ContainedSimpleField\n if (o[lenField.name] == null) {\n this.WriteTagEquals(lenField.definition.tag)\n buffer.writeWholeNumber(b.length)\n buffer.writeChar(delimiter)\n }\n this.WriteTagEquals(tag)\n buffer.writeBuffer(b)\n posValBegin = buffer.getPos()\n break\n }\n\n default: {\n buffer.writeString(val as string)\n break\n }\n }\n\n this.writeDelimiter(posValBegin, tag)\n\n switch (tag) {\n case Tags.BodyLengthTag:\n this.bodyLengthPos = pos + 2\n break\n\n case Tags.MsgTag:\n this.msgTypePos = pos\n break\n }\n }\n}\n\nclass GroupValidator {\n constructor (public readonly gf: ContainedGroupField,\n public readonly first: AsciiEncodeSetSummary = new AsciiEncodeSetSummary(),\n public readonly test: AsciiEncodeSetSummary = new AsciiEncodeSetSummary()) {\n }\n\n getSummary (field: number): AsciiEncodeSetSummary {\n return field === 0 ? this.first : this.test\n }\n\n assertInstanceValid (field: number): void {\n const first = this.first\n const test = this.test\n if (field === 0 && first.empty()) {\n throw new Error(`first group instance has no delimiter present ${this.gf.name}`)\n }\n if (field > 0 && test.empty()) {\n throw new Error(`group instance [${field}] has no delimiter present ${this.gf.name}`)\n }\n if (field > 0) {\n const firstTag = first.firstSimple?.definition.tag\n const tag = test.firstSimple?.definition.tag\n if (firstTag !== tag) {\n const msg = `group instance [${field}] inconsistent delimiter ${tag} expected tag ${firstTag}`\n throw new Error(msg)\n }\n }\n }\n}\n\nclass AsciiEncodeSetSummary {\n constructor (public firstSimple: ContainedSimpleField | null = null,\n public lastSimple: ContainedSimpleField | null = null,\n public count: number = 0) {\n }\n\n public reset (): void {\n this.firstSimple = null\n this.lastSimple = null\n this.count = 0\n }\n\n public empty (): boolean {\n return this.firstSimple === null || this.count === 0\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ascii-encoder.js","sourceRoot":"","sources":["../../../src/buffer/ascii/ascii-encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { ILooseObject } from '../../collections/collection'\nimport {\n ContainedGroupField, ContainedSimpleField,\n IContainedSet, ContainedField,\n ContainedComponentField, FieldsDispatch\n} from '../../dictionary/contained'\nimport { SimpleFieldDefinition, FixDefinitions } from '../../dictionary/definition'\nimport { MsgEncoder } from '../msg-encoder'\nimport { ElasticBuffer } from '../elastic-buffer'\nimport { TimeFormatter } from './time-formatter'\nimport { ITimeFormatter } from './itime-formatter'\nimport { AsciiChars } from './ascii-chars'\nimport { Tags } from '../tag/tags'\nimport { TagType } from '../tag/tag-type'\n\nexport class AsciiEncoder extends MsgEncoder {\n public bodyLengthPos: number\n public msgTypePos: number\n public tags: Tags\n public checkGroups: boolean = true\n readonly dispatcher: FieldsDispatch = new FieldsDispatch()\n\n constructor (public readonly buffer: ElasticBuffer,\n public readonly definitions: FixDefinitions,\n public readonly timeFormatter: ITimeFormatter = new TimeFormatter(buffer),\n public readonly delimiter: number = AsciiChars.Soh,\n public readonly logDelimiter: number = AsciiChars.Pipe) {\n super(definitions)\n this.tags = new Tags()\n }\n\n public trim (): Buffer {\n const b = this.buffer.copy()\n const delimiter = this.delimiter\n const logDelimiter = this.logDelimiter\n const tags = this.tags\n if (delimiter !== logDelimiter) {\n for (let p = 0; p < tags.nextTagPos; ++p) {\n const tagPos = tags.tagPos[p]\n b.writeUInt8(delimiter, tagPos.start + tagPos.len)\n }\n }\n\n return b\n }\n\n // only reset tags after entire message is encoded - <hdr>body<trl>\n\n public reset (): void {\n this.buffer.reset()\n this.tags.reset()\n }\n\n public encodeSet (objectToEncode: ILooseObject, set: IContainedSet): void {\n const summary: AsciiEncodeSetSummary = new AsciiEncodeSetSummary()\n this.encodeObject(objectToEncode, set, summary)\n }\n\n private encodeObject (objectToEncode: ILooseObject, set: IContainedSet, state: AsciiEncodeSetSummary): void {\n const fields: ContainedField[] = this.getFields(set, objectToEncode)\n this.dispatcher.dispatchFields(fields, {\n simple: (sf: ContainedSimpleField) => {\n const val: any = objectToEncode[sf.name]\n // Empty strings are omitted as they result in empty values for tags, which are considered malformed.\n if (val != null && val !== '') {\n if (state.count === 0) {\n state.firstSimple = sf\n }\n state.lastSimple = sf\n state.count++\n this.encodeSimple(objectToEncode, set, sf, val)\n }\n },\n component: (cf: ContainedComponentField) => {\n const instance: ILooseObject = objectToEncode[cf.definition.name]\n if (instance) {\n this.encodeObject(instance, cf.definition, state)\n }\n },\n group: (gf: ContainedGroupField) => {\n this.encodeInstances(objectToEncode, gf)\n }\n })\n }\n\n private getFields (set: IContainedSet, o: ILooseObject): ContainedField[] {\n const keys: string[] = Object.keys(o)\n let j: number = 0\n const fields: ContainedField[] = keys.reduce((a: ContainedField[], current: string) => {\n const field = set.localNameToField.get(current)\n if (field) {\n a[j++] = field\n } else if (this.onUnknownField && !AsciiEncoder.expectedMiss(set, current)) {\n this.onUnknownField(current, set.name)\n }\n return a\n }, new Array(keys.length))\n fields.sort((a: ContainedField, b: ContainedField) => a.position - b.position)\n return fields\n }\n\n /**\n * Keys that legitimately fail to resolve against this set, so reporting them would\n * be noise: the header and trailer are encoded separately by the transmitter, and\n * a repeating group may be keyed by its count field rather than the group name -\n * encodeInstances accepts either.\n */\n private static expectedMiss (set: IContainedSet, name: string): boolean {\n if (name === 'StandardHeader' || name === 'StandardTrailer') {\n return true\n }\n for (const group of set.groups.values()) {\n if ((group as any).noOfField?.name === name) {\n return true\n }\n }\n return false\n }\n\n private encodeInstances (o: ILooseObject, gf: ContainedGroupField): void {\n const noOfField: SimpleFieldDefinition | null = gf.definition.noOfField\n if (!noOfField) return\n const instances: ILooseObject[] = o[gf.name] || o[noOfField.name]\n\n const buffer = this.buffer\n if (!Array.isArray(instances)) {\n throw new Error(`expected array instance for group ${noOfField.name}`)\n }\n if (instances) {\n const validator = new GroupValidator(gf)\n const test: AsciiEncodeSetSummary = validator.test\n\n // a repeated group has number of instances at the start of group\n this.WriteTagEquals(noOfField.tag)\n const posValBegin = buffer.getPos()\n buffer.writeWholeNumber(instances.length)\n this.writeDelimiter(posValBegin, noOfField.tag)\n for (let field = 0; field < instances.length; ++field) {\n const instance: ILooseObject = instances[field]\n test.reset()\n const summary = validator.getSummary(field)\n this.encodeObject(instance, gf.definition, summary)\n if (this.checkGroups) {\n validator.assertInstanceValid(field)\n }\n }\n }\n }\n\n private WriteTagEquals (tag: number): void {\n const buffer = this.buffer\n buffer.writeWholeNumber(tag)\n buffer.writeChar(AsciiChars.Equal)\n }\n\n private writeDelimiter (posValBegin: number, tag: number): void {\n const delimiter = this.logDelimiter\n const buffer = this.buffer\n this.tags.store(posValBegin, buffer.getPos() - posValBegin, tag)\n buffer.writeChar(delimiter)\n }\n\n private encodeSimple (o: ILooseObject, set: IContainedSet, sf: ContainedSimpleField, val: any): void {\n const definition = sf.definition\n const tag: number = definition.tag\n const buffer = this.buffer\n const delimiter = this.logDelimiter\n const tf = this.timeFormatter\n const pos = buffer.getPos()\n let posValBegin = 0\n\n let tagType: TagType\n if (typeof val === 'string') {\n switch (definition.tagType) {\n case TagType.Boolean: {\n tagType = definition.tagType\n const vs: string = val\n const first: string = vs.length > 0 ? vs.charAt(0) : 'N'\n val = first === 'Y' || first === 'T'\n break\n }\n default: {\n tagType = TagType.String\n }\n }\n } else {\n tagType = definition.tagType\n }\n\n switch (tagType) {\n case TagType.RawData: {\n // may need to first write raw message length (see below)\n break\n }\n\n default: {\n this.WriteTagEquals(tag)\n posValBegin = buffer.getPos()\n break\n }\n }\n\n switch (tagType) {\n case TagType.String: {\n buffer.writeString(val as string)\n break\n }\n\n case TagType.Float: {\n buffer.writeNumber(val as number)\n break\n }\n\n case TagType.Int:\n case TagType.Length: {\n buffer.writeWholeNumber(val as number)\n break\n }\n\n case TagType.Boolean: {\n buffer.writeBoolean(val as boolean)\n break\n }\n\n case TagType.UtcTimestamp: {\n tf.writeUtcTimestamp(val as Date)\n break\n }\n\n case TagType.UtcTimeOnly: {\n tf.writeUtcTime(val as Date)\n break\n }\n\n case TagType.UtcDateOnly: {\n tf.writeUtcDate(val as Date)\n break\n }\n\n case TagType.LocalDate: {\n tf.writeLocalDate(val as Date)\n break\n }\n\n case TagType.RawData: {\n const b = val as Buffer\n const lenField: ContainedSimpleField = set.fields[sf.position - 1] as ContainedSimpleField\n if (o[lenField.name] == null) {\n this.WriteTagEquals(lenField.definition.tag)\n buffer.writeWholeNumber(b.length)\n buffer.writeChar(delimiter)\n }\n this.WriteTagEquals(tag)\n buffer.writeBuffer(b)\n posValBegin = buffer.getPos()\n break\n }\n\n default: {\n buffer.writeString(val as string)\n break\n }\n }\n\n this.writeDelimiter(posValBegin, tag)\n\n switch (tag) {\n case Tags.BodyLengthTag:\n this.bodyLengthPos = pos + 2\n break\n\n case Tags.MsgTag:\n this.msgTypePos = pos\n break\n }\n }\n}\n\nclass GroupValidator {\n constructor (public readonly gf: ContainedGroupField,\n public readonly first: AsciiEncodeSetSummary = new AsciiEncodeSetSummary(),\n public readonly test: AsciiEncodeSetSummary = new AsciiEncodeSetSummary()) {\n }\n\n getSummary (field: number): AsciiEncodeSetSummary {\n return field === 0 ? this.first : this.test\n }\n\n assertInstanceValid (field: number): void {\n const first = this.first\n const test = this.test\n if (field === 0 && first.empty()) {\n throw new Error(`first group instance has no delimiter present ${this.gf.name}`)\n }\n if (field > 0 && test.empty()) {\n throw new Error(`group instance [${field}] has no delimiter present ${this.gf.name}`)\n }\n if (field > 0) {\n const firstTag = first.firstSimple?.definition.tag\n const tag = test.firstSimple?.definition.tag\n if (firstTag !== tag) {\n const msg = `group instance [${field}] inconsistent delimiter ${tag} expected tag ${firstTag}`\n throw new Error(msg)\n }\n }\n }\n}\n\nclass AsciiEncodeSetSummary {\n constructor (public firstSimple: ContainedSimpleField | null = null,\n public lastSimple: ContainedSimpleField | null = null,\n public count: number = 0) {\n }\n\n public reset (): void {\n this.firstSimple = null\n this.lastSimple = null\n this.count = 0\n }\n\n public empty (): boolean {\n return this.firstSimple === null || this.count === 0\n }\n}\n"]}
|
|
@@ -41,7 +41,7 @@ let AsciiParser = AsciiParser_1 = class AsciiParser extends msg_parser_1.MsgPars
|
|
|
41
41
|
this.id = AsciiParser_1.nextId++;
|
|
42
42
|
this.segmentParser = config.sessionContainer.resolve(ascii_segment_parser_1.AsciiSegmentParser);
|
|
43
43
|
this.state = config.sessionContainer.resolve(ascii_parser_state_1.AsciiParserState);
|
|
44
|
-
this.state.locations = new tags_1.Tags(this.receivingBuffer.size / 10, this.maxMessageLen);
|
|
44
|
+
this.state.locations = new tags_1.Tags(Math.floor(this.receivingBuffer.size / 10), this.maxMessageLen);
|
|
45
45
|
this.state.definitions = this.config.definitions;
|
|
46
46
|
this.state.beginMessage();
|
|
47
47
|
if (readStream !== null) {
|
|
@@ -92,6 +92,9 @@ let AsciiParser = AsciiParser_1 = class AsciiParser extends msg_parser_1.MsgPars
|
|
|
92
92
|
const buff = Buffer.from(text);
|
|
93
93
|
this.parse(buff, buff.length);
|
|
94
94
|
}
|
|
95
|
+
parseBuffer(buff, end = buff.length) {
|
|
96
|
+
this.parse(buff, end);
|
|
97
|
+
}
|
|
95
98
|
parse(readBuffer, end) {
|
|
96
99
|
const state = this.state;
|
|
97
100
|
const eq = ascii_chars_1.AsciiChars.Eq;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ascii-parser.js","sourceRoot":"","sources":["../../../src/buffer/ascii/ascii-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsciiChars } from './ascii-chars'\nimport { AsciiView } from './ascii-view'\nimport { AsciiSegmentParser } from './ascii-segment-parser'\nimport { AsciiParserState } from './ascii-parser-state'\nimport { Structure } from '../structure'\nimport { Tags } from '../tag/tags'\nimport { MsgParser } from '../msg-parser'\nimport { MsgView } from '../msg-view'\nimport { Readable } from 'stream'\nimport { ElasticBuffer } from '../elastic-buffer'\nimport { SegmentDescription } from '../segment/segment-description'\nimport { ParseState } from './parse-state'\nimport { IJsFixConfig } from '../../config/js-fix-config'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { SegmentType } from '../segment/segment-type'\nimport { AsciiParserError } from './ascii-segment-parser-error'\n\n@injectable()\nexport class AsciiParser extends MsgParser {\n private static nextId: number = 0\n public readonly id: number\n public readonly state: AsciiParserState\n private readonly segmentParser: AsciiSegmentParser\n public readonly delimiter: number\n public readonly writeDelimiter: number\n\n // allocate enough in receive buffer so buffer does not constant resize back after large messages\n // want to keep one slice of memory and constantly reuse it\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly config: IJsFixConfig,\n @inject(DITokens.readStream) public readonly readStream: Readable | null,\n @inject(DITokens.ParseBuffer) protected readonly receivingBuffer: ElasticBuffer,\n @inject(DITokens.maxMessageLen) public readonly maxMessageLen: number = 160 * 1024) {\n super()\n\n this.delimiter = config.delimiter ?? AsciiChars.Soh\n this.writeDelimiter = config.logDelimiter ?? AsciiChars.Pipe\n this.id = AsciiParser.nextId++\n this.segmentParser = config.sessionContainer.resolve<AsciiSegmentParser>(AsciiSegmentParser)\n this.state = config.sessionContainer.resolve<AsciiParserState>(AsciiParserState)\n this.state.locations = new Tags(this.receivingBuffer.size / 10, this.maxMessageLen)\n this.state.definitions = this.config.definitions\n this.state.beginMessage()\n if (readStream !== null) {\n this.subscribe()\n }\n }\n\n private subscribe (): void {\n const inst: AsciiParser = this\n const Writable = require('stream').Writable\n const stream = this.readStream\n\n const receiver = new Writable({\n write: (data: Buffer, _: any, done: Function) => {\n try {\n inst.parse(data, data.length)\n done()\n } catch (e) {\n done(e)\n }\n }\n })\n receiver.on('error', (e: Error) => {\n this.emit('error', e)\n })\n\n // receive from say a socket or file and pipe to parser which discovers messages\n stream?.pipe(receiver).on('finish', () => {\n this.emit('done')\n })\n stream?.on('error', (e) => {\n this.emit('error', e)\n })\n stream?.on('end', () => {\n this.emit('end')\n })\n }\n\n public reset (): void {\n this.state.beginMessage()\n }\n\n private msg (ptr: number): void {\n const receivingBuffer: ElasticBuffer = this.receivingBuffer\n const state = this.state\n if (this.listeners('decoded')) {\n this.emit('decoded', state.msgType, receivingBuffer, ptr)\n }\n this.emit('msg', state.msgType, this.getView(ptr))\n state.beginMessage()\n }\n\n /**\n * useful helper for testing where characters are parsed as if from the transport\n * @param text to be parsed\n */\n public parseText (text: string): void {\n const buff = Buffer.from(text)\n this.parse(buff, buff.length)\n }\n\n private parse (readBuffer: Buffer, end: number): void {\n const state = this.state\n const eq: number = AsciiChars.Eq\n const zero: number = AsciiChars.Zero\n const nine: number = AsciiChars.Nine\n const delimiter: number = this.delimiter\n const writeDelimiter: number = this.writeDelimiter\n const receivingBuffer: ElasticBuffer = this.receivingBuffer\n const switchDelimiter = writeDelimiter !== delimiter\n let readPtr: number = 0\n\n while (readPtr < end) {\n const charAtPos: number = readBuffer[readPtr]\n\n const writePtr = receivingBuffer.saveChar(charAtPos) - 1\n switch (state.parseState) {\n case ParseState.MsgComplete: {\n this.msg(writePtr)\n continue\n }\n\n case ParseState.BeginField: {\n const atDigit: boolean = charAtPos >= zero && charAtPos <= nine\n if (atDigit) {\n state.beginTag(writePtr)\n }\n break\n }\n\n case ParseState.ParsingTag: {\n const isEquals: boolean = charAtPos === eq\n if (isEquals) {\n state.endTag(writePtr)\n }\n break\n }\n\n case ParseState.ParsingRawData: {\n // keep skipping until length read, regardless of delimiter or not\n if (state.incRaw()) {\n // having consumed the declared raw data length, expect delimiter.\n // if not found (e.g. replayed messages with pretty-printed XML where\n // the stored length undershoots), keep scanning forward to the actual\n // delimiter rather than throwing.\n if (charAtPos === delimiter) {\n if (switchDelimiter) {\n receivingBuffer.switchChar(writeDelimiter)\n }\n state.store()\n }\n } else if (charAtPos === delimiter) {\n // hit delimiter before declared length exhausted — store what we have\n if (switchDelimiter) {\n receivingBuffer.switchChar(writeDelimiter)\n }\n state.store()\n }\n break\n }\n\n case ParseState.ParsingRawDataLength:\n case ParseState.ParsingValue: {\n if (charAtPos === delimiter) {\n if (switchDelimiter) {\n receivingBuffer.switchChar(writeDelimiter)\n }\n state.store()\n }\n break\n }\n\n default: {\n const st = state.parseState\n throw new Error(`fix parser in unknown state ${st}`)\n }\n }\n readPtr++\n }\n\n switch (state.parseState) {\n case ParseState.MsgComplete: {\n this.msg(receivingBuffer.getPos())\n break\n }\n }\n }\n\n private getView (ptr: number): MsgView | null {\n const state = this.state\n const locations = state.locations\n const source = this.receivingBuffer\n const delimiter = this.delimiter\n const definitions = this.config.definitions\n const replace = this.writeDelimiter\n const msgType = state.msgType ?? null\n if (!msgType) return null\n if (state.message) {\n try {\n const structure: Structure | null = this.segmentParser.parse(msgType, locations,\n locations.nextTagPos - 1)\n if (!structure) return null\n return new AsciiView(definitions, structure.msg(),\n source,\n structure,\n ptr,\n delimiter,\n replace)\n } catch (error) {\n if (error instanceof AsciiParserError) {\n error.summary.buffer = source.toString()\n this.emit('error', error)\n }\n throw error\n }\n }\n\n const structure = new Structure(locations, [])\n const segment = new SegmentDescription('unknown', locations.tagPos[0].tag, null, 0, 1, SegmentType.Unknown)\n segment.endPosition = locations.nextTagPos - 1\n return new AsciiView(this.config.definitions, segment, source, structure, ptr, delimiter, replace)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ascii-parser.js","sourceRoot":"","sources":["../../../src/buffer/ascii/ascii-parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsciiChars } from './ascii-chars'\nimport { AsciiView } from './ascii-view'\nimport { AsciiSegmentParser } from './ascii-segment-parser'\nimport { AsciiParserState } from './ascii-parser-state'\nimport { Structure } from '../structure'\nimport { Tags } from '../tag/tags'\nimport { MsgParser } from '../msg-parser'\nimport { MsgView } from '../msg-view'\nimport { Readable } from 'stream'\nimport { ElasticBuffer } from '../elastic-buffer'\nimport { SegmentDescription } from '../segment/segment-description'\nimport { ParseState } from './parse-state'\nimport { IJsFixConfig } from '../../config/js-fix-config'\nimport { inject, injectable } from 'tsyringe'\nimport { DITokens } from '../../runtime/di-tokens'\nimport { SegmentType } from '../segment/segment-type'\nimport { AsciiParserError } from './ascii-segment-parser-error'\n\n@injectable()\nexport class AsciiParser extends MsgParser {\n private static nextId: number = 0\n public readonly id: number\n public readonly state: AsciiParserState\n private readonly segmentParser: AsciiSegmentParser\n public readonly delimiter: number\n public readonly writeDelimiter: number\n\n // allocate enough in receive buffer so buffer does not constant resize back after large messages\n // want to keep one slice of memory and constantly reuse it\n\n constructor (@inject(DITokens.IJsFixConfig) public readonly config: IJsFixConfig,\n @inject(DITokens.readStream) public readonly readStream: Readable | null,\n @inject(DITokens.ParseBuffer) protected readonly receivingBuffer: ElasticBuffer,\n @inject(DITokens.maxMessageLen) public readonly maxMessageLen: number = 160 * 1024) {\n super()\n\n this.delimiter = config.delimiter ?? AsciiChars.Soh\n this.writeDelimiter = config.logDelimiter ?? AsciiChars.Pipe\n this.id = AsciiParser.nextId++\n this.segmentParser = config.sessionContainer.resolve<AsciiSegmentParser>(AsciiSegmentParser)\n this.state = config.sessionContainer.resolve<AsciiParserState>(AsciiParserState)\n // floored - Tags hands the starting length to new Array, which rejects a\n // fraction, so any buffer size not divisible by 10 threw from here\n this.state.locations = new Tags(Math.floor(this.receivingBuffer.size / 10), this.maxMessageLen)\n this.state.definitions = this.config.definitions\n this.state.beginMessage()\n if (readStream !== null) {\n this.subscribe()\n }\n }\n\n private subscribe (): void {\n const inst: AsciiParser = this\n const Writable = require('stream').Writable\n const stream = this.readStream\n\n const receiver = new Writable({\n write: (data: Buffer, _: any, done: Function) => {\n try {\n inst.parse(data, data.length)\n done()\n } catch (e) {\n done(e)\n }\n }\n })\n receiver.on('error', (e: Error) => {\n this.emit('error', e)\n })\n\n // receive from say a socket or file and pipe to parser which discovers messages\n stream?.pipe(receiver).on('finish', () => {\n this.emit('done')\n })\n stream?.on('error', (e) => {\n this.emit('error', e)\n })\n stream?.on('end', () => {\n this.emit('end')\n })\n }\n\n public reset (): void {\n this.state.beginMessage()\n }\n\n private msg (ptr: number): void {\n const receivingBuffer: ElasticBuffer = this.receivingBuffer\n const state = this.state\n if (this.listeners('decoded')) {\n this.emit('decoded', state.msgType, receivingBuffer, ptr)\n }\n this.emit('msg', state.msgType, this.getView(ptr))\n state.beginMessage()\n }\n\n /**\n * useful helper for testing where characters are parsed as if from the transport\n * @param text to be parsed\n */\n public parseText (text: string): void {\n const buff = Buffer.from(text)\n this.parse(buff, buff.length)\n }\n\n /**\n * feed bytes as though they had arrived from the transport. This is the path\n * the socket takes - subscribe hands each chunk it receives straight to parse -\n * so a caller driving the parser directly, a benchmark or a replay harness,\n * measures the real thing rather than a copy of it.\n *\n * @param buff bytes to parse\n * @param end how much of buff to consume, all of it by default\n */\n public parseBuffer (buff: Buffer, end: number = buff.length): void {\n this.parse(buff, end)\n }\n\n private parse (readBuffer: Buffer, end: number): void {\n const state = this.state\n const eq: number = AsciiChars.Eq\n const zero: number = AsciiChars.Zero\n const nine: number = AsciiChars.Nine\n const delimiter: number = this.delimiter\n const writeDelimiter: number = this.writeDelimiter\n const receivingBuffer: ElasticBuffer = this.receivingBuffer\n const switchDelimiter = writeDelimiter !== delimiter\n let readPtr: number = 0\n\n while (readPtr < end) {\n const charAtPos: number = readBuffer[readPtr]\n\n const writePtr = receivingBuffer.saveChar(charAtPos) - 1\n switch (state.parseState) {\n case ParseState.MsgComplete: {\n this.msg(writePtr)\n continue\n }\n\n case ParseState.BeginField: {\n const atDigit: boolean = charAtPos >= zero && charAtPos <= nine\n if (atDigit) {\n state.beginTag(writePtr)\n }\n break\n }\n\n case ParseState.ParsingTag: {\n const isEquals: boolean = charAtPos === eq\n if (isEquals) {\n state.endTag(writePtr)\n }\n break\n }\n\n case ParseState.ParsingRawData: {\n // keep skipping until length read, regardless of delimiter or not\n if (state.incRaw()) {\n // having consumed the declared raw data length, expect delimiter.\n // if not found (e.g. replayed messages with pretty-printed XML where\n // the stored length undershoots), keep scanning forward to the actual\n // delimiter rather than throwing.\n if (charAtPos === delimiter) {\n if (switchDelimiter) {\n receivingBuffer.switchChar(writeDelimiter)\n }\n state.store()\n }\n } else if (charAtPos === delimiter) {\n // hit delimiter before declared length exhausted — store what we have\n if (switchDelimiter) {\n receivingBuffer.switchChar(writeDelimiter)\n }\n state.store()\n }\n break\n }\n\n case ParseState.ParsingRawDataLength:\n case ParseState.ParsingValue: {\n if (charAtPos === delimiter) {\n if (switchDelimiter) {\n receivingBuffer.switchChar(writeDelimiter)\n }\n state.store()\n }\n break\n }\n\n default: {\n const st = state.parseState\n throw new Error(`fix parser in unknown state ${st}`)\n }\n }\n readPtr++\n }\n\n switch (state.parseState) {\n case ParseState.MsgComplete: {\n this.msg(receivingBuffer.getPos())\n break\n }\n }\n }\n\n private getView (ptr: number): MsgView | null {\n const state = this.state\n const locations = state.locations\n const source = this.receivingBuffer\n const delimiter = this.delimiter\n const definitions = this.config.definitions\n const replace = this.writeDelimiter\n const msgType = state.msgType ?? null\n if (!msgType) return null\n if (state.message) {\n try {\n const structure: Structure | null = this.segmentParser.parse(msgType, locations,\n locations.nextTagPos - 1)\n if (!structure) return null\n return new AsciiView(definitions, structure.msg(),\n source,\n structure,\n ptr,\n delimiter,\n replace)\n } catch (error) {\n if (error instanceof AsciiParserError) {\n error.summary.buffer = source.toString()\n this.emit('error', error)\n }\n throw error\n }\n }\n\n const structure = new Structure(locations, [])\n const segment = new SegmentDescription('unknown', locations.tagPos[0].tag, null, 0, 1, SegmentType.Unknown)\n segment.endPosition = locations.nextTagPos - 1\n return new AsciiView(this.config.definitions, segment, source, structure, ptr, delimiter, replace)\n }\n}\n"]}
|