@bepalo/rjson 1.0.0 → 1.0.5

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/src/index.ts CHANGED
@@ -1,2 +1,632 @@
1
- export * from "./rjson.ts";
2
- export { default } from "./rjson.ts";
1
+ const Constants = {
2
+ ObjectStart: "(".charCodeAt(0),
3
+ ObjectEnd: ")".charCodeAt(0),
4
+ ArrayStart0: "_".charCodeAt(0),
5
+ ArrayStart1: "(".charCodeAt(0),
6
+ ArrayEnd0: ")".charCodeAt(0),
7
+ ArrayEnd1: "_".charCodeAt(0),
8
+ MappedStart0: "~".charCodeAt(0),
9
+ MappedStart1: "(".charCodeAt(0),
10
+ MappedEnd0: ")".charCodeAt(0),
11
+ MappedEnd1: "~".charCodeAt(0),
12
+ STRSSingle: "'".charCodeAt(0),
13
+ STRESingle: "'".charCodeAt(0),
14
+ STRSDouble: '"'.charCodeAt(0),
15
+ STREDouble: '"'.charCodeAt(0),
16
+ STRSTick: "`".charCodeAt(0),
17
+ STRETick: "`".charCodeAt(0),
18
+ Escape: "\\".charCodeAt(0),
19
+ CCA: "A".charCodeAt(0),
20
+ CCZ: "Z".charCodeAt(0),
21
+ CCa: "a".charCodeAt(0),
22
+ CCz: "z".charCodeAt(0),
23
+ CCUnderScore: "_".charCodeAt(0),
24
+ CCDot: ".".charCodeAt(0),
25
+ CC0: "0".charCodeAt(0),
26
+ CC9: "9".charCodeAt(0),
27
+ CCE: "E".charCodeAt(0),
28
+ CCe: "e".charCodeAt(0),
29
+ CCMinus: "-".charCodeAt(0),
30
+ CCPlus: "+".charCodeAt(0),
31
+ CCDecimalPoint: ".".charCodeAt(0),
32
+ CCC: ":".charCodeAt(0),
33
+ CCKeyValueSeparator: ":".charCodeAt(0),
34
+ CCValueSeparator: ",".charCodeAt(0),
35
+ CCTrue: "T".charCodeAt(0),
36
+ CCFalse: "F".charCodeAt(0),
37
+ CCNull: "N".charCodeAt(0),
38
+ CCUndefined: "U".charCodeAt(0),
39
+ } as const;
40
+
41
+ interface ParseRJSONState {
42
+ start: number;
43
+ end: number;
44
+ i: number;
45
+ charCode: number;
46
+ forbidTextKeys?: boolean;
47
+ forbidEmptyKeys?: boolean;
48
+ }
49
+
50
+ const isAlpha = (charCode: number): boolean =>
51
+ (charCode >= Constants.CCa && charCode <= Constants.CCz) ||
52
+ (charCode >= Constants.CCA && charCode <= Constants.CCZ);
53
+
54
+ const isDigit = (charCode: number): boolean =>
55
+ charCode >= Constants.CC0 && charCode <= Constants.CC9;
56
+
57
+ const isIdentifier0 = (charCode: number): boolean =>
58
+ isAlpha(charCode) || charCode === Constants.CCUnderScore;
59
+
60
+ const isIdentifier1 = (charCode: number): boolean =>
61
+ isAlpha(charCode) ||
62
+ isDigit(charCode) ||
63
+ charCode === Constants.CCUnderScore ||
64
+ charCode === Constants.CCDot;
65
+
66
+ const throwRJSONError = (
67
+ source: string,
68
+ _state: ParseRJSONState,
69
+ message: string,
70
+ index: number,
71
+ token: string,
72
+ ) => {
73
+ throw new Error(
74
+ `'${message}' '${token}' at index ${index}\n\`\n${source.slice(
75
+ Math.max(0, index - 20),
76
+ index + 1,
77
+ )}\n\``,
78
+ );
79
+ };
80
+
81
+ const parseRJSONKey = (
82
+ source: string,
83
+ state: ParseRJSONState,
84
+ separatorCharCode: number,
85
+ endCharCode: number,
86
+ ): string => {
87
+ // first char
88
+ {
89
+ state.charCode = source.charCodeAt(state.i);
90
+ switch (state.charCode) {
91
+ case separatorCharCode:
92
+ case endCharCode:
93
+ if (state.forbidEmptyKeys) {
94
+ return throwRJSONError(
95
+ source,
96
+ state,
97
+ "Empty object key is forbidden in this context",
98
+ state.i,
99
+ source.charAt(state.i),
100
+ );
101
+ }
102
+ return "";
103
+ case Constants.STRSSingle:
104
+ case Constants.STRSDouble:
105
+ case Constants.STRSTick:
106
+ if (state.forbidTextKeys) {
107
+ return throwRJSONError(
108
+ source,
109
+ state,
110
+ "Text object key is forbidden in this context",
111
+ state.i,
112
+ source.charAt(state.i),
113
+ );
114
+ }
115
+ return parseRJSONText(source, state);
116
+ }
117
+ if (!isIdentifier0(state.charCode)) {
118
+ return throwRJSONError(
119
+ source,
120
+ state,
121
+ "Invalid object key start token",
122
+ state.i,
123
+ source.charAt(state.i),
124
+ );
125
+ }
126
+ }
127
+ const s = state.i;
128
+ for (state.i++; state.i < state.end; state.i++) {
129
+ state.charCode = source.charCodeAt(state.i);
130
+ if (
131
+ state.charCode === separatorCharCode ||
132
+ state.charCode === endCharCode
133
+ ) {
134
+ break;
135
+ } else if (!isIdentifier1(state.charCode)) {
136
+ return throwRJSONError(
137
+ source,
138
+ state,
139
+ "Invalid object key token",
140
+ state.i,
141
+ source.charAt(state.i),
142
+ );
143
+ }
144
+ }
145
+ return source.slice(s, state.i);
146
+ };
147
+
148
+ const parseRJSONText = (source: string, state: ParseRJSONState): string => {
149
+ const textDelimiter = state.charCode;
150
+ const s = ++state.i;
151
+ let j = s;
152
+ let result = "";
153
+ for (; state.i < state.end; state.i++) {
154
+ state.charCode = source.charCodeAt(state.i);
155
+ if (state.charCode === Constants.Escape) {
156
+ result += source.slice(j, state.i);
157
+ j = ++state.i;
158
+ continue;
159
+ } else if (state.charCode === textDelimiter) {
160
+ result += source.slice(j, state.i);
161
+ state.i++;
162
+ break;
163
+ }
164
+ }
165
+ return result;
166
+ };
167
+
168
+ const praseRJSONNumber = (
169
+ source: string,
170
+ state: ParseRJSONState,
171
+ endCharCode?: number,
172
+ ): number => {
173
+ const s = state.i;
174
+ let decimalPointsCount = state.charCode === Constants.CCDecimalPoint ? 1 : 0;
175
+ let eCount =
176
+ state.charCode === Constants.CCE || state.charCode === Constants.CCe
177
+ ? 1
178
+ : 0;
179
+ for (state.i++; state.i < state.end; state.i++) {
180
+ state.charCode = source.charCodeAt(state.i);
181
+ if (state.charCode === Constants.CCValueSeparator) {
182
+ break;
183
+ }
184
+ switch (state.charCode) {
185
+ case Constants.CCDecimalPoint:
186
+ if (decimalPointsCount > 0) {
187
+ return throwRJSONError(
188
+ source,
189
+ state,
190
+ "Invalid decimal token",
191
+ state.i,
192
+ source.charAt(state.i),
193
+ );
194
+ }
195
+ decimalPointsCount++;
196
+ continue;
197
+ case Constants.CCE:
198
+ case Constants.CCe:
199
+ if (eCount > 0) {
200
+ return throwRJSONError(
201
+ source,
202
+ state,
203
+ "Invalid 'e' token",
204
+ state.i,
205
+ source.charAt(state.i),
206
+ );
207
+ }
208
+ eCount++;
209
+ continue;
210
+ case Constants.CCMinus:
211
+ case Constants.CCPlus:
212
+ if (eCount === 0) {
213
+ return throwRJSONError(
214
+ source,
215
+ state,
216
+ "Invalid sign token",
217
+ state.i,
218
+ source.charAt(state.i),
219
+ );
220
+ }
221
+ continue;
222
+ case 48:
223
+ case 49:
224
+ case 50:
225
+ case 51:
226
+ case 52:
227
+ case 53:
228
+ case 54:
229
+ case 55:
230
+ case 56:
231
+ case 57:
232
+ continue;
233
+ }
234
+ if (state.charCode === endCharCode) {
235
+ break;
236
+ }
237
+ return throwRJSONError(
238
+ source,
239
+ state,
240
+ "Invalid numeric value token",
241
+ state.i,
242
+ source.charAt(state.i),
243
+ );
244
+ }
245
+ return Number.parseFloat(source.slice(s, state.i));
246
+ };
247
+
248
+ const parseRJSONValue = (
249
+ source: string,
250
+ state: ParseRJSONState,
251
+ endCharCode?: number,
252
+ ): string | number | boolean | undefined | null => {
253
+ state.charCode = source.charCodeAt(state.i);
254
+ switch (state.charCode) {
255
+ case Constants.CCValueSeparator:
256
+ case Constants.ObjectEnd:
257
+ case Constants.ArrayEnd0: {
258
+ return null;
259
+ }
260
+ case Constants.CCNull: {
261
+ state.i++;
262
+ return null;
263
+ }
264
+ case Constants.CCUndefined: {
265
+ state.i++;
266
+ return undefined;
267
+ }
268
+ case Constants.CCTrue:
269
+ case Constants.CCFalse: {
270
+ state.i++;
271
+ return state.charCode === Constants.CCTrue;
272
+ }
273
+ case Constants.STRSSingle:
274
+ case Constants.STRSDouble:
275
+ case Constants.STRSTick: {
276
+ return parseRJSONText(source, state);
277
+ }
278
+ case Constants.CCMinus:
279
+ case Constants.CCPlus:
280
+ case Constants.CCDecimalPoint: {
281
+ return praseRJSONNumber(source, state, endCharCode);
282
+ }
283
+ default: {
284
+ if (
285
+ !isDigit(state.charCode) &&
286
+ state.charCode !== Constants.CCDecimalPoint
287
+ ) {
288
+ if (endCharCode != null && state.charCode === endCharCode) {
289
+ break;
290
+ }
291
+ return throwRJSONError(
292
+ source,
293
+ state,
294
+ "Invalid token",
295
+ state.i,
296
+ source.charAt(state.i),
297
+ );
298
+ }
299
+ return praseRJSONNumber(source, state, endCharCode);
300
+ }
301
+ }
302
+ };
303
+
304
+ const parseRJSONArray = (source: string, state: ParseRJSONState): unknown[] => {
305
+ state.charCode = source.charCodeAt(state.i);
306
+ if (state.charCode !== Constants.ArrayStart0) {
307
+ return throwRJSONError(
308
+ source,
309
+ state,
310
+ "Invalid array start token",
311
+ state.i,
312
+ source.charAt(state.i),
313
+ );
314
+ }
315
+ state.charCode = source.charCodeAt(++state.i);
316
+ if (state.charCode !== Constants.ArrayStart1) {
317
+ return throwRJSONError(
318
+ source,
319
+ state,
320
+ "Invalid array start token",
321
+ state.i,
322
+ source.charAt(state.i),
323
+ );
324
+ }
325
+ const result: Array<unknown> = [];
326
+ for (state.i++; state.i < state.end; state.i++) {
327
+ state.charCode = source.charCodeAt(state.i);
328
+ const value = parseRJSONEntity(source, state, Constants.ArrayEnd0);
329
+ result.push(value);
330
+ state.charCode = source.charCodeAt(state.i);
331
+ if (state.charCode === Constants.ArrayEnd0) {
332
+ break;
333
+ }
334
+ }
335
+ state.charCode = source.charCodeAt(state.i);
336
+ if (state.charCode !== Constants.ArrayEnd0) {
337
+ return throwRJSONError(
338
+ source,
339
+ state,
340
+ "Invalid array end token",
341
+ state.i,
342
+ source.charAt(state.i),
343
+ );
344
+ }
345
+ state.charCode = source.charCodeAt(++state.i);
346
+ if (state.charCode !== Constants.ArrayEnd1) {
347
+ return throwRJSONError(
348
+ source,
349
+ state,
350
+ "Invalid array end token",
351
+ state.i,
352
+ source.charAt(state.i),
353
+ );
354
+ }
355
+ state.i++;
356
+ return result;
357
+ };
358
+
359
+ const parseRJSONMappedArray = (
360
+ source: string,
361
+ state: ParseRJSONState,
362
+ ): Record<string, unknown> => {
363
+ state.charCode = source.charCodeAt(state.i++);
364
+ if (state.charCode !== Constants.MappedStart0) {
365
+ return throwRJSONError(
366
+ source,
367
+ state,
368
+ "Invalid mapped array start token",
369
+ state.i,
370
+ source.charAt(state.i),
371
+ );
372
+ }
373
+ const value = parseRJSONEntity(source, state, Constants.MappedStart1);
374
+ state.charCode = source.charCodeAt(state.i);
375
+ if (state.charCode !== Constants.MappedStart1) {
376
+ return throwRJSONError(
377
+ source,
378
+ state,
379
+ "Invalid mapped array start token",
380
+ state.i,
381
+ source.charAt(state.i),
382
+ );
383
+ }
384
+ const result: Record<string, unknown> = {};
385
+ for (state.i++; state.i < state.end; state.i++) {
386
+ state.charCode = source.charCodeAt(state.i);
387
+ if (state.charCode === Constants.MappedEnd0) {
388
+ break;
389
+ }
390
+ const key = parseRJSONKey(
391
+ source,
392
+ state,
393
+ Constants.CCValueSeparator,
394
+ Constants.MappedEnd0,
395
+ );
396
+ result[key] = value;
397
+ state.charCode = source.charCodeAt(state.i);
398
+ if (state.charCode === Constants.MappedEnd0) {
399
+ break;
400
+ }
401
+ }
402
+ state.charCode = source.charCodeAt(state.i);
403
+ if (state.charCode !== Constants.MappedEnd0) {
404
+ return throwRJSONError(
405
+ source,
406
+ state,
407
+ "Invalid mapped array end token",
408
+ state.i,
409
+ source.charAt(state.i),
410
+ );
411
+ }
412
+ state.charCode = source.charCodeAt(++state.i);
413
+ if (state.charCode !== Constants.MappedEnd1) {
414
+ return throwRJSONError(
415
+ source,
416
+ state,
417
+ "Invalid mapped array end token",
418
+ state.i,
419
+ source.charAt(state.i),
420
+ );
421
+ }
422
+ state.i++;
423
+ return result;
424
+ };
425
+
426
+ const parseRJSONObject = (
427
+ source: string,
428
+ state: ParseRJSONState,
429
+ ): Record<string, unknown> => {
430
+ state.charCode = source.charCodeAt(state.i);
431
+ if (state.charCode !== Constants.ObjectStart) {
432
+ return throwRJSONError(
433
+ source,
434
+ state,
435
+ "Invalid object start token",
436
+ state.i,
437
+ source.charAt(state.i),
438
+ );
439
+ }
440
+ if (state.charCode === Constants.ObjectEnd) {
441
+ return {};
442
+ }
443
+ const result: Record<string, unknown> = {};
444
+ for (state.i++; state.i < state.end; state.i++) {
445
+ state.charCode = source.charCodeAt(state.i);
446
+ if (state.charCode === Constants.ObjectEnd) {
447
+ break;
448
+ }
449
+ const key = parseRJSONKey(
450
+ source,
451
+ state,
452
+ Constants.CCKeyValueSeparator,
453
+ Constants.ObjectEnd,
454
+ );
455
+ state.charCode = source.charCodeAt(state.i);
456
+ if (state.charCode === Constants.CCKeyValueSeparator) {
457
+ state.i++;
458
+ }
459
+ const value = parseRJSONEntity(source, state, Constants.ObjectEnd);
460
+ result[key] = value;
461
+ state.charCode = source.charCodeAt(state.i);
462
+ if (state.charCode === Constants.ObjectEnd) {
463
+ break;
464
+ }
465
+ }
466
+ state.charCode = source.charCodeAt(state.i);
467
+ if (state.charCode !== Constants.ObjectEnd) {
468
+ return throwRJSONError(
469
+ source,
470
+ state,
471
+ "Invalid object end token",
472
+ state.i,
473
+ source.charAt(state.i),
474
+ );
475
+ }
476
+ state.i++;
477
+ return result;
478
+ };
479
+
480
+ const parseRJSONEntity = (
481
+ source: string,
482
+ state: ParseRJSONState,
483
+ endCharCode?: number,
484
+ ): unknown => {
485
+ state.charCode = source.charCodeAt(state.i);
486
+ switch (state.charCode) {
487
+ case Constants.ArrayStart0:
488
+ return parseRJSONArray(source, state);
489
+ case Constants.ObjectStart:
490
+ return parseRJSONObject(source, state);
491
+ case Constants.MappedStart0:
492
+ return parseRJSONMappedArray(source, state);
493
+ default:
494
+ return parseRJSONValue(source, state, endCharCode);
495
+ }
496
+ };
497
+
498
+ export const parseRJSON = (
499
+ source: string,
500
+ initalState?: Partial<ParseRJSONState>,
501
+ ): unknown => {
502
+ if (source.length === 0) {
503
+ return null;
504
+ }
505
+ const state: ParseRJSONState = {
506
+ start: 0,
507
+ end: source.length,
508
+ i: 0,
509
+ charCode: source.charCodeAt(0),
510
+ ...initalState,
511
+ };
512
+ const result = parseRJSONEntity(source, state);
513
+ if (state.i < source.length) {
514
+ return throwRJSONError(
515
+ source,
516
+ state,
517
+ "Extra tokens at the end",
518
+ state.i,
519
+ source.length - state.i > 20
520
+ ? source.slice(state.i, Math.min(state.i + 20, source.length)) + "..."
521
+ : source.slice(state.i),
522
+ );
523
+ }
524
+ return result;
525
+ };
526
+
527
+ export function rjson(
528
+ strings: TemplateStringsArray,
529
+ ...values: unknown[]
530
+ ): unknown {
531
+ const source =
532
+ values.length === 0
533
+ ? strings[0]
534
+ : strings[0] + values.map((v, i) => `${v}${values[i]}`).join("");
535
+ return parseRJSON(source as string);
536
+ }
537
+
538
+ export const stringifyRJSONKey = (key: string): string => {
539
+ if (key.length === 0) {
540
+ return "";
541
+ }
542
+ {
543
+ const charCode = key.charCodeAt(0);
544
+ if (!isIdentifier0(charCode)) {
545
+ return `'${key}'`;
546
+ }
547
+ }
548
+ for (let i = 1; i < key.length; i++) {
549
+ const charCode = key.charCodeAt(i);
550
+ if (!isIdentifier1(charCode)) {
551
+ return `'${key}'`;
552
+ }
553
+ }
554
+ return key;
555
+ };
556
+
557
+ export const stringifyRJSONArray = (data: unknown[]): string => {
558
+ return `_(${data.map((d) => stringifyRJSON(d)).join(",")})_`;
559
+ };
560
+
561
+ export const stringifyRJSONObject = (data: Record<string, unknown>): string => {
562
+ return `(${Object.entries(data)
563
+ .map(([k, v]) => `${stringifyRJSONKey(k)}:${stringifyRJSON(v)}`)
564
+ .join(",")})`;
565
+ };
566
+
567
+ export const stringifyRJSONMappedArray = (
568
+ value: unknown | undefined | null,
569
+ data: unknown[],
570
+ ): string => {
571
+ return `~${stringifyRJSON(value)}(${data.map((d) => stringifyRJSONKey(String(d))).join(",")})~`;
572
+ };
573
+
574
+ export const stringifyRJSONString = (data: string): string => {
575
+ return !data.includes("'")
576
+ ? `'${data}'`
577
+ : !data.includes('"')
578
+ ? `"${data}"`
579
+ : !data.includes("`")
580
+ ? `\`${data}\``
581
+ : `'${data.replace("'", "\\'")}'`;
582
+ };
583
+
584
+ export const stringifyRJSONNumber = (data: number): string => {
585
+ if (!Number.isFinite(data)) {
586
+ return "N";
587
+ } else if (data === 0) {
588
+ return "0";
589
+ }
590
+ const expo = data.toExponential();
591
+ const norm = data.toString();
592
+ return norm.length <= expo.length ? norm : expo;
593
+ };
594
+
595
+ export const stringifyRJSONBoolean = (data: boolean): string => {
596
+ return data ? "T" : "F";
597
+ };
598
+
599
+ export const stringifyRJSON = (data?: unknown): string => {
600
+ if (data === undefined) {
601
+ return "U";
602
+ } else if (data === null) {
603
+ return "";
604
+ }
605
+ switch (typeof data) {
606
+ case "object":
607
+ return Array.isArray(data)
608
+ ? stringifyRJSONArray(data)
609
+ : stringifyRJSONObject(data as Record<string, unknown>);
610
+ case "string":
611
+ return stringifyRJSONString(data);
612
+ case "number":
613
+ return stringifyRJSONNumber(data);
614
+ case "boolean":
615
+ return stringifyRJSONBoolean(data);
616
+ default:
617
+ return stringifyRJSONString(String(data));
618
+ }
619
+ };
620
+
621
+ export const RJSON = {
622
+ parse: parseRJSON,
623
+ stringify: stringifyRJSON,
624
+ stringifyKey: stringifyRJSONKey,
625
+ stringifyObject: stringifyRJSONObject,
626
+ stringifyMappedArray: stringifyRJSONMappedArray,
627
+ stringifyString: stringifyRJSONString,
628
+ stringifyNumber: stringifyRJSONNumber,
629
+ stringifyBoolean: stringifyRJSONBoolean,
630
+ };
631
+
632
+ export default RJSON;
@@ -1,30 +0,0 @@
1
- interface ParseRJSONState {
2
- start: number;
3
- end: number;
4
- i: number;
5
- charCode: number;
6
- forbidTextKeys?: boolean;
7
- forbidEmptyKeys?: boolean;
8
- }
9
- export declare const parseRJSON: (source: string, initalState?: Partial<ParseRJSONState>) => unknown;
10
- export declare function rjson(strings: TemplateStringsArray, ...values: unknown[]): unknown;
11
- export declare const stringifyRJSONKey: (key: string) => string;
12
- export declare const stringifyRJSONArray: (data: unknown[]) => string;
13
- export declare const stringifyRJSONObject: (data: Record<string, unknown>) => string;
14
- export declare const stringifyRJSONMappedArray: (value: unknown | undefined | null, data: unknown[]) => string;
15
- export declare const stringifyRJSONString: (data: string) => string;
16
- export declare const stringifyRJSONNumber: (data: number) => string;
17
- export declare const stringifyRJSONBoolean: (data: boolean) => string;
18
- export declare const stringifyRJSON: (data?: unknown) => string;
19
- export declare const RJSON: {
20
- parse: (source: string, initalState?: Partial<ParseRJSONState>) => unknown;
21
- stringify: (data?: unknown) => string;
22
- stringifyKey: (key: string) => string;
23
- stringifyObject: (data: Record<string, unknown>) => string;
24
- stringifyMappedArray: (value: unknown | undefined | null, data: unknown[]) => string;
25
- stringifyString: (data: string) => string;
26
- stringifyNumber: (data: number) => string;
27
- stringifyBoolean: (data: boolean) => string;
28
- };
29
- export default RJSON;
30
- //# sourceMappingURL=rjson.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rjson.d.ts","sourceRoot":"","sources":["../../src/rjson.ts"],"names":[],"mappings":"AAwCA,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA8bD,eAAO,MAAM,UAAU,GACrB,QAAQ,MAAM,EACd,cAAc,OAAO,CAAC,eAAe,CAAC,KACrC,OAwBF,CAAC;AAEF,wBAAgB,KAAK,CACnB,OAAO,EAAE,oBAAoB,EAC7B,GAAG,MAAM,EAAE,OAAO,EAAE,GACnB,OAAO,CAKT;AAED,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,KAAG,MAiB/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,MAAM,OAAO,EAAE,KAAG,MAErD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAMpE,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,OAAO,OAAO,GAAG,SAAS,GAAG,IAAI,EACjC,MAAM,OAAO,EAAE,KACd,MAEF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MAQnD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,MASnD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,OAAO,KAAG,MAErD,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAoB/C,CAAC;AAEF,eAAO,MAAM,KAAK;oBA3HR,MAAM,gBACA,OAAO,CAAC,eAAe,CAAC,KACrC,OAAO;uBAmG4B,OAAO,KAAG,MAAM;wBA/Df,MAAM,KAAG,MAAM;4BAuBX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM;kCASlE,OAAO,GAAG,SAAS,GAAG,IAAI,QAC3B,OAAO,EAAE,KACd,MAAM;4BAIkC,MAAM,KAAG,MAAM;4BAUf,MAAM,KAAG,MAAM;6BAWd,OAAO,KAAG,MAAM;CAmC3D,CAAC;AAEF,eAAe,KAAK,CAAC"}