split-frames 2.4.5 → 2.5.1

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.
@@ -0,0 +1,385 @@
1
+ "use strict";
2
+ // deps
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ // natives
8
+ const node_stream_1 = require("node:stream");
9
+ // locals
10
+ const initData_1 = __importDefault(require("./checkers/initData"));
11
+ // module
12
+ class SplitFrames extends node_stream_1.Transform {
13
+ // constructor
14
+ constructor(options) {
15
+ super();
16
+ this._frame = Buffer.from([]);
17
+ this._digesting = false;
18
+ this._timeoutDigest = null;
19
+ // from params
20
+ const validatedOptions = (0, initData_1.default)(options);
21
+ this._startWith = validatedOptions.startWith;
22
+ this._startTimeout = validatedOptions.startTimeout;
23
+ this._endWith = validatedOptions.endWith;
24
+ this._escapeWith = validatedOptions.escapeWith;
25
+ this._escaped = validatedOptions.escaped;
26
+ this._specifics = validatedOptions.specifics;
27
+ this._controlBits = validatedOptions.controlBits;
28
+ // dynamic digester
29
+ this._digester = this._chooseDigester();
30
+ }
31
+ // methods
32
+ // public
33
+ _transform(chunk, enc, cb) {
34
+ if (chunk.length) {
35
+ this._frame = Buffer.concat([this._frame, chunk]);
36
+ if (!this._digesting) {
37
+ this._digest(enc);
38
+ }
39
+ }
40
+ return cb();
41
+ }
42
+ // protected
43
+ _chooseDigester() {
44
+ let digester = undefined;
45
+ if (undefined === this._startWith && undefined === this._endWith) {
46
+ digester = this._digestNoStartNoEnd;
47
+ }
48
+ else if (undefined !== this._startWith && undefined === this._endWith) {
49
+ digester = this._digestStartOnly;
50
+ }
51
+ else if (undefined === this._startWith && undefined !== this._endWith) {
52
+ digester = this._digestEndOnly;
53
+ }
54
+ else {
55
+ digester = this._digestStartAndEnd;
56
+ }
57
+ return digester;
58
+ }
59
+ _digest(enc) {
60
+ if (!this._frame.length) {
61
+ this._digesting = false;
62
+ }
63
+ else {
64
+ this._digesting = true;
65
+ try {
66
+ this._digester(enc);
67
+ }
68
+ catch (e) {
69
+ this.emit("error", e);
70
+ }
71
+ }
72
+ }
73
+ // private
74
+ // digesters
75
+ _digestNoStartNoEnd() {
76
+ const KEYS = Object.keys(this._specifics);
77
+ if (KEYS.length) {
78
+ KEYS.forEach((key) => {
79
+ const size = "object" === typeof this._specifics[key] && this._specifics[key] instanceof Buffer ? this._specifics[key].length : 1;
80
+ for (let foundAt = this._searchTags(this._specifics[key]); -1 < foundAt; foundAt = this._searchTags(this._specifics[key])) {
81
+ this.emit(key);
82
+ this._frame = Buffer.from(Buffer.concat([
83
+ this._frame.slice(0, foundAt),
84
+ this._frame.slice(foundAt + size, this._frame.length)
85
+ ]));
86
+ }
87
+ });
88
+ }
89
+ this.push(Buffer.from(this._frame));
90
+ this._frame = Buffer.from([]);
91
+ this._digesting = false;
92
+ }
93
+ _digestStartOnly(enc) {
94
+ if (this._timeoutDigest) {
95
+ clearTimeout(this._timeoutDigest);
96
+ this._timeoutDigest = null;
97
+ }
98
+ const firstStart = this._searchFirstStart();
99
+ // no start tag detected
100
+ if (!firstStart) {
101
+ this._digesting = false;
102
+ }
103
+ // first start tag detected
104
+ else {
105
+ const nextStartAt = this._searchTags(this._startWith, firstStart.end);
106
+ // second start tag not detected
107
+ if (-1 >= nextStartAt) {
108
+ // remove useless bits
109
+ this._frame = 0 < firstStart.start ? Buffer.from(this._frame.slice(firstStart.start, this._frame.length)) : this._frame;
110
+ this._digesting = false;
111
+ this._timeoutDigest = setTimeout(() => {
112
+ clearTimeout(this._timeoutDigest);
113
+ this._timeoutDigest = null;
114
+ this.push(Buffer.from(this._frame.slice(firstStart.start, this._frame.length)));
115
+ this._frame = Buffer.from([]);
116
+ this._digesting = false;
117
+ }, this._startTimeout);
118
+ }
119
+ // second start tag detected
120
+ else {
121
+ // extract first frame
122
+ this.push(Buffer.from(this._frame.slice(firstStart.start, nextStartAt)));
123
+ // remove extracted frame from main one
124
+ this._frame = Buffer.from(this._frame.slice(nextStartAt, this._frame.length));
125
+ // second full frame detected (force minimal data length)
126
+ if (-1 < this._searchTags(this._startWith, 1)) {
127
+ this._digest(enc);
128
+ }
129
+ else {
130
+ this._digesting = false;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ _digestEndOnly(enc) {
136
+ this._extractSpecifics();
137
+ const firstEnd = this._searchFirstEnd(0);
138
+ // no end tag detected
139
+ if (!firstEnd) {
140
+ this._digesting = false;
141
+ }
142
+ // first end tag detected
143
+ else {
144
+ // extract first frame
145
+ this.push(Buffer.from(this._frame.slice(0, firstEnd.end)));
146
+ // remove extracted frame from main one
147
+ this._frame = Buffer.from(this._frame.slice(firstEnd.end, this._frame.length));
148
+ // second full frame detected
149
+ if (-1 < this._searchTags(this._endWith)) {
150
+ this._digest(enc);
151
+ }
152
+ else {
153
+ this._digesting = false;
154
+ }
155
+ }
156
+ }
157
+ _extractSpecifics() {
158
+ let found = false;
159
+ Object.keys(this._specifics).forEach((key) => {
160
+ if (0 === this._frame.indexOf(this._specifics[key])) {
161
+ found = true;
162
+ const size = "object" === typeof this._specifics[key] && this._specifics[key] instanceof Buffer
163
+ ? this._specifics[key].length
164
+ : 1;
165
+ this.emit(key);
166
+ this._frame = Buffer.from(this._frame.slice(size, this._frame.length));
167
+ }
168
+ });
169
+ if (found) {
170
+ this._extractSpecifics();
171
+ }
172
+ }
173
+ _digestStartAndEnd(enc) {
174
+ const KEYS = Object.keys(this._specifics);
175
+ if (KEYS.length) {
176
+ KEYS.forEach((key) => {
177
+ const firstStart = this._searchFirstStart();
178
+ const size = "object" === typeof this._specifics[key] && this._specifics[key] instanceof Buffer ? this._specifics[key].length : 1;
179
+ for (let foundAt = this._searchTags(this._specifics[key]), i = 0; -1 < foundAt && (!firstStart || foundAt < firstStart.start - i); foundAt = this._searchTags(this._specifics[key]), i += size) {
180
+ this.emit(key);
181
+ this._frame = Buffer.from(Buffer.concat([
182
+ this._frame.slice(0, foundAt),
183
+ this._frame.slice(foundAt + size, this._frame.length)
184
+ ]));
185
+ }
186
+ });
187
+ }
188
+ const firstStart = this._searchFirstStart();
189
+ // no start tag detected
190
+ if (!firstStart) {
191
+ this._digesting = false;
192
+ }
193
+ // start tag detected
194
+ else {
195
+ const firstEnd = this._searchFirstEnd(firstStart.end);
196
+ // end tag not detected
197
+ if (!firstEnd) {
198
+ // remove useless bits
199
+ this._frame = 0 < firstStart.start ? Buffer.from(this._frame.slice(firstStart.start, this._frame.length)) : this._frame;
200
+ this._digesting = false;
201
+ }
202
+ // end tag detected
203
+ else {
204
+ this.push(Buffer.from(this._frame.slice(firstStart.start, firstEnd.end)));
205
+ // remove extracted frame from main one
206
+ this._frame = Buffer.from(this._frame.slice(firstEnd.end, this._frame.length));
207
+ // search specifics
208
+ let foundSpecific = false;
209
+ for (let i = 0; i < KEYS.length && !foundSpecific; ++i) {
210
+ if (-1 < this._searchTags(this._specifics[KEYS[i]])) {
211
+ foundSpecific = true;
212
+ break;
213
+ }
214
+ }
215
+ // specific detected or second start detected (force minimal data length)
216
+ if (foundSpecific || -1 < this._searchTags(this._startWith, 1)) {
217
+ this._digest(enc);
218
+ }
219
+ else {
220
+ this._digesting = false;
221
+ }
222
+ }
223
+ }
224
+ }
225
+ // search tag
226
+ _searchFirstTag(tag, beginAt = 0) {
227
+ let startAt = -1;
228
+ let endAt = -1;
229
+ // number
230
+ if ("number" === typeof tag) {
231
+ const find = this._searchFirstNumberTag(tag, beginAt);
232
+ startAt = find.start;
233
+ endAt = find.end;
234
+ }
235
+ // Buffer | Array
236
+ else if ("object" === typeof tag) {
237
+ const find = this._searchFirstBufferOrArrayTag(tag, beginAt);
238
+ startAt = find.start;
239
+ endAt = find.end;
240
+ }
241
+ // not found
242
+ if (-1 >= startAt || -1 >= endAt) {
243
+ return undefined;
244
+ }
245
+ // escaped
246
+ else if (0 < startAt
247
+ && 1 === endAt - startAt // must be a number to be escaped
248
+ && this._escaped.includes(this._frame[startAt])
249
+ && this._frame[startAt - 1] === this._escapeWith) {
250
+ // escaper not escaped
251
+ if (!this._escaped.includes(this._escapeWith) || 1 >= startAt || this._frame[startAt - 2] !== this._escapeWith) {
252
+ return this._searchFirstTag(tag, endAt + 1);
253
+ }
254
+ else {
255
+ return {
256
+ "start": startAt,
257
+ "end": endAt
258
+ };
259
+ }
260
+ }
261
+ // not escaped
262
+ else {
263
+ return {
264
+ "start": startAt,
265
+ "end": endAt
266
+ };
267
+ }
268
+ }
269
+ _searchFirstNumberTag(tag, beginAt) {
270
+ const startAt = this._frame.indexOf(tag, beginAt);
271
+ return {
272
+ "start": startAt,
273
+ "end": startAt + 1
274
+ };
275
+ }
276
+ _searchFirstBufferOrArrayTag(tag, beginAt) {
277
+ let startAt = -1;
278
+ let endAt = -1;
279
+ // Buffer
280
+ if (tag instanceof Buffer) {
281
+ startAt = this._frame.indexOf(tag, beginAt);
282
+ if (-1 < startAt) {
283
+ endAt = startAt + tag.length;
284
+ }
285
+ }
286
+ // Array
287
+ else if (tag instanceof Array) {
288
+ for (let i = 0; i < tag.length; ++i) {
289
+ // number | Buffer
290
+ if ("number" === typeof tag[i]
291
+ || ("object" === typeof tag[i] && tag[i] instanceof Buffer)) {
292
+ const _startAt = this._frame.indexOf(tag[i], beginAt);
293
+ if (-1 < _startAt && (-1 >= startAt || _startAt < startAt)) {
294
+ startAt = _startAt;
295
+ if (-1 < startAt) {
296
+ endAt = startAt + ("number" === typeof tag[i] ? 1 : tag[i].length);
297
+ }
298
+ }
299
+ }
300
+ }
301
+ }
302
+ return {
303
+ "start": startAt,
304
+ "end": endAt
305
+ };
306
+ }
307
+ _searchFirstStart() {
308
+ return this._searchFirstTag(this._startWith);
309
+ }
310
+ _searchFirstEnd(startEndAt) {
311
+ const firstTag = this._searchFirstTag(this._endWith, startEndAt);
312
+ if (firstTag) {
313
+ if ("end+1" === this._controlBits) {
314
+ firstTag.end += 1;
315
+ }
316
+ else if ("end+2" === this._controlBits) {
317
+ firstTag.end += 2;
318
+ }
319
+ // end tag detected but without valid control bits length
320
+ if (firstTag.end > this._frame.length) {
321
+ return undefined;
322
+ }
323
+ }
324
+ return firstTag;
325
+ }
326
+ _searchTags(tags, beginAt = 0) {
327
+ // number
328
+ if ("number" === typeof tags) {
329
+ return this._searchNumberTags(tags, beginAt);
330
+ }
331
+ // Buffer | Array
332
+ else if ("object" === typeof tags) {
333
+ return this._searchBufferOrArrayTags(tags, beginAt);
334
+ }
335
+ return -1;
336
+ }
337
+ _searchNumberTags(tags, beginAt) {
338
+ const foundAt = this._frame.indexOf(tags, beginAt);
339
+ // escaped
340
+ if (0 < foundAt
341
+ && this._escaped.includes(this._frame[foundAt])
342
+ && this._frame[foundAt - 1] === this._escapeWith) {
343
+ // escaper not escaped
344
+ if (!this._escaped.includes(this._escapeWith) || 1 >= foundAt || this._frame[foundAt - 2] !== this._escapeWith) {
345
+ return this._searchTags(tags, foundAt + 1);
346
+ }
347
+ }
348
+ return foundAt;
349
+ }
350
+ _searchBufferOrArrayTags(tags, beginAt) {
351
+ // Buffer
352
+ if (tags instanceof Buffer) {
353
+ return this._frame.indexOf(tags, beginAt);
354
+ }
355
+ // Array
356
+ else if (tags instanceof Array) {
357
+ let foundAt = -1;
358
+ let type = "undefined";
359
+ for (let i = 0; i < tags.length; ++i) {
360
+ // number | Buffer
361
+ if ("number" === typeof tags[i]
362
+ || ("object" === typeof tags[i]
363
+ && tags[i] instanceof Buffer)) {
364
+ const _foundAt = this._frame.indexOf(tags[i], beginAt);
365
+ if (-1 < _foundAt && (-1 >= foundAt || _foundAt < foundAt)) {
366
+ foundAt = _foundAt;
367
+ type = typeof tags[i];
368
+ }
369
+ }
370
+ }
371
+ // escaped
372
+ if ("number" === type && 0 < foundAt
373
+ && this._escaped.includes(this._frame[foundAt])
374
+ && this._frame[foundAt - 1] === this._escapeWith) {
375
+ // escaper not escaped
376
+ if (!this._escaped.includes(this._escapeWith) || 1 >= foundAt || this._frame[foundAt - 2] !== this._escapeWith) {
377
+ foundAt = this._searchTags(tags, foundAt + 1);
378
+ }
379
+ }
380
+ return foundAt;
381
+ }
382
+ return -1;
383
+ }
384
+ }
385
+ exports.default = SplitFrames;
@@ -0,0 +1,2 @@
1
+ import type { tTag } from "../SplitFrames.js";
2
+ export default function checkTagsValidity(tags: tTag): boolean;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ // types & interfaces
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.default = checkTagsValidity;
5
+ // module
6
+ function checkTagsValidity(tags) {
7
+ let result = true;
8
+ if ("number" !== typeof tags && "object" !== typeof tags) {
9
+ result = false;
10
+ }
11
+ else if ("object" === typeof tags && tags instanceof Array) {
12
+ for (let i = 0; i < tags.length; ++i) {
13
+ if ("number" !== typeof tags[i] && "object" !== typeof tags[i] && !(tags[i] instanceof Buffer)) {
14
+ result = false;
15
+ break;
16
+ }
17
+ }
18
+ }
19
+ return result;
20
+ }
@@ -0,0 +1,2 @@
1
+ import type { iOptions, iConf } from "../SplitFrames.js";
2
+ export default function initData(options?: iOptions): iConf;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ // deps
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.default = initData;
8
+ // locals
9
+ const checkTagsValidity_1 = __importDefault(require("./checkTagsValidity"));
10
+ // consts
11
+ const ALLOWED_CONTROL_BITS_OPTIONS = [
12
+ "none",
13
+ "end+1",
14
+ "end+2"
15
+ ];
16
+ // module
17
+ function initData(options) {
18
+ const result = {
19
+ "startWith": undefined,
20
+ "startTimeout": 200,
21
+ "endWith": undefined,
22
+ "escapeWith": undefined,
23
+ "escaped": [],
24
+ "specifics": {},
25
+ "controlBits": "none"
26
+ };
27
+ if ("undefined" !== typeof options) {
28
+ if ("object" !== typeof options) {
29
+ throw new TypeError("parameter sended is not an object");
30
+ }
31
+ else if ("undefined" !== typeof options.startWith && !(0, checkTagsValidity_1.default)(options.startWith)) {
32
+ throw new TypeError("startWith parameter sended is not a number, Buffer, or an Array of numbers");
33
+ }
34
+ else if ("undefined" !== typeof options.startTimeout && "number" !== typeof options.startTimeout) {
35
+ throw new TypeError("startTimeout parameter sended is not a number");
36
+ }
37
+ else if ("undefined" !== typeof options.endWith && !(0, checkTagsValidity_1.default)(options.endWith)) {
38
+ throw new TypeError("endWith parameter sended is not a number, Buffer, or an Array of numbers");
39
+ }
40
+ else if ("undefined" !== typeof options.escapeWith && "number" !== typeof options.escapeWith) {
41
+ throw new TypeError("escapeWith parameter sended is not a number");
42
+ }
43
+ else if ("undefined" !== typeof options.specifics && "object" !== typeof options.specifics) {
44
+ throw new TypeError("escapeWith parameter sended is not an object");
45
+ }
46
+ else if ("undefined" !== typeof options.controlBits && "string" !== typeof options.controlBits) {
47
+ throw new TypeError("controlBits parameter sended is not a string");
48
+ }
49
+ else if ("undefined" !== typeof options.controlBits && !ALLOWED_CONTROL_BITS_OPTIONS.includes(options.controlBits)) {
50
+ throw new Error("controlBits option sended is not in [ \"" + ALLOWED_CONTROL_BITS_OPTIONS.join("\", \"") + "\" ]");
51
+ }
52
+ else {
53
+ result.startWith = "undefined" !== typeof options.startWith ? options.startWith : undefined;
54
+ result.endWith = "undefined" !== typeof options.endWith ? options.endWith : undefined;
55
+ if ("undefined" !== typeof options.startTimeout) {
56
+ result.startTimeout = options.startTimeout;
57
+ }
58
+ result.escapeWith = "undefined" !== typeof options.escapeWith ? options.escapeWith : undefined;
59
+ if ("undefined" !== typeof options.escaped) {
60
+ result.escaped = options.escaped;
61
+ }
62
+ for (let i = 0; i < result.escaped.length; ++i) {
63
+ if ("number" !== typeof result.escaped[i]) {
64
+ throw new TypeError("escaped parameter n°" + i + " sended is not a number");
65
+ }
66
+ }
67
+ if ("object" === typeof options.specifics) {
68
+ const specifics = options.specifics;
69
+ Object.keys(specifics).forEach((key) => {
70
+ if ("undefined" !== typeof specifics[key]) {
71
+ if (!(0, checkTagsValidity_1.default)(specifics[key])) {
72
+ throw new Error("\"" + specifics[key] + "\" specifics option"
73
+ + " sended is not a number, or an Array of numbers");
74
+ }
75
+ else if (undefined !== specifics[key]
76
+ && undefined !== result.startWith
77
+ && undefined === result.endWith) {
78
+ throw new Error("If you want to use \"" + specifics[key] + "\" specific option,"
79
+ + " you have to use \"endWith\" option");
80
+ }
81
+ }
82
+ });
83
+ }
84
+ result.specifics = "undefined" !== typeof options.specifics ? options.specifics : {};
85
+ result.controlBits = "undefined" !== typeof options.controlBits ? options.controlBits : "none";
86
+ }
87
+ }
88
+ return result;
89
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ // deps
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ // locals
7
+ const SplitFrames_1 = __importDefault(require("./SplitFrames"));
8
+ module.exports = SplitFrames_1.default;
@@ -0,0 +1,2 @@
1
+ import SplitFrames from "./SplitFrames";
2
+ export = SplitFrames;