@aidc-toolkit/utility 0.9.8-beta → 0.9.9-beta
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/LICENSE +0 -27
- package/README.md +14 -0
- package/dist/index.cjs +95 -74
- package/dist/index.d.cts +71 -550
- package/dist/index.d.ts +71 -550
- package/dist/index.js +91 -70
- package/package.json +8 -8
- package/src/character-set.ts +1 -1
- package/src/index.ts +17 -1
- package/src/locale/en/locale-strings.ts +2 -2
- package/src/locale/fr/locale-strings.ts +2 -2
- package/src/locale/i18n.ts +3 -2
- package/src/{sequencer.ts → sequence.ts} +12 -12
- package/src/transformer.ts +102 -99
- package/test/character-set.test.ts +4 -4
- package/test/{sequencer.test.ts → sequence.test.ts} +16 -16
- package/test/transformer.test.ts +20 -21
package/src/transformer.ts
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import { i18nextUtility } from "./locale/i18n.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Sequence } from "./sequence.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Transformer
|
|
5
|
+
* Transformer primitive type.
|
|
6
|
+
*/
|
|
7
|
+
export type TransformerPrimitive = string | number | bigint | boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Transformer input type, one of:
|
|
6
11
|
*
|
|
7
|
-
* -
|
|
8
|
-
* - Iterable<
|
|
12
|
+
* - TInput (primitive type)
|
|
13
|
+
* - Iterable<TInput>
|
|
9
14
|
*
|
|
10
|
-
* @template
|
|
11
|
-
*
|
|
15
|
+
* @template TInput
|
|
16
|
+
* Transformer input primitive type.
|
|
12
17
|
*/
|
|
13
|
-
export type TransformerInput<
|
|
18
|
+
export type TransformerInput<TInput extends TransformerPrimitive> = TInput | Iterable<TInput>;
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* Transformer callback, used to convert transformed value to its final value.
|
|
17
22
|
*
|
|
18
23
|
* @template TInput
|
|
19
|
-
*
|
|
24
|
+
* Transformer input primitive type.
|
|
20
25
|
*
|
|
21
26
|
* @template TOutput
|
|
22
|
-
*
|
|
27
|
+
* Transformer output type.
|
|
23
28
|
*
|
|
24
29
|
* @param input
|
|
25
30
|
* Input value.
|
|
@@ -30,42 +35,48 @@ export type TransformerInput<T extends string | number | bigint | boolean> = T |
|
|
|
30
35
|
* @returns
|
|
31
36
|
* Output value.
|
|
32
37
|
*/
|
|
33
|
-
export type TransformerCallback<TInput, TOutput> = (input: TInput, index: number) => TOutput;
|
|
38
|
+
export type TransformerCallback<TInput extends TransformerPrimitive, TOutput> = (input: TInput, index: number) => TOutput;
|
|
34
39
|
|
|
35
40
|
/**
|
|
36
41
|
* Transformer output, based on transformer input:
|
|
37
42
|
*
|
|
38
|
-
* - If type
|
|
39
|
-
* - If type
|
|
43
|
+
* - If type TTransformerInput is primitive, result is type TOutput.
|
|
44
|
+
* - If type TTransformerInput is Iterable, result is type Iterable<TOutput>.
|
|
40
45
|
*
|
|
41
|
-
* @template
|
|
46
|
+
* @template TTransformerInput
|
|
42
47
|
* Transformer input type.
|
|
43
48
|
*
|
|
44
49
|
* @template TOutput
|
|
45
50
|
* Output base type.
|
|
46
51
|
*/
|
|
47
|
-
export type TransformerOutput<
|
|
48
|
-
|
|
52
|
+
export type TransformerOutput<TTransformerInput extends TransformerInput<TransformerPrimitive>, TOutput> =
|
|
53
|
+
TTransformerInput extends (TTransformerInput extends TransformerInput<infer TInput> ? TInput : never) ? TOutput : Iterable<TOutput>;
|
|
49
54
|
|
|
50
55
|
/**
|
|
51
|
-
* Transform an iterable
|
|
56
|
+
* Transform an input iterable to an output iterable that applies a transformer callback to each value in the input.
|
|
52
57
|
*
|
|
53
|
-
* @param
|
|
54
|
-
* Input iterable.
|
|
58
|
+
* @param values
|
|
59
|
+
* Input values iterable.
|
|
55
60
|
*
|
|
56
61
|
* @param transformerCallback
|
|
57
62
|
* Callback to transform input value to output value.
|
|
58
63
|
*
|
|
59
64
|
* @returns
|
|
60
|
-
* Output iterable.
|
|
65
|
+
* Output values iterable.
|
|
61
66
|
*/
|
|
62
|
-
export function transformIterable<TInput, TOutput>(
|
|
67
|
+
export function transformIterable<TInput extends TransformerPrimitive, TOutput>(values: Iterable<TInput>, transformerCallback: TransformerCallback<TInput, TOutput>): Iterable<TOutput> {
|
|
63
68
|
return {
|
|
69
|
+
/**
|
|
70
|
+
* Iterable implementation.
|
|
71
|
+
*
|
|
72
|
+
* @yields
|
|
73
|
+
* Next output value.
|
|
74
|
+
*/
|
|
64
75
|
* [Symbol.iterator](): Generator<TOutput> {
|
|
65
76
|
let index = 0;
|
|
66
77
|
|
|
67
|
-
for (const
|
|
68
|
-
yield transformerCallback(
|
|
78
|
+
for (const value of values) {
|
|
79
|
+
yield transformerCallback(value, index++);
|
|
69
80
|
}
|
|
70
81
|
}
|
|
71
82
|
};
|
|
@@ -191,32 +202,68 @@ export abstract class Transformer {
|
|
|
191
202
|
*/
|
|
192
203
|
protected abstract doForward(value: bigint): bigint;
|
|
193
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Validate that a value is within the domain and do the work of transforming it forward.
|
|
207
|
+
*
|
|
208
|
+
* @param value
|
|
209
|
+
* Value.
|
|
210
|
+
*
|
|
211
|
+
* @returns
|
|
212
|
+
* Transformed value.
|
|
213
|
+
*/
|
|
214
|
+
private validateDoForward(value: number | bigint): bigint {
|
|
215
|
+
const valueN = BigInt(value);
|
|
216
|
+
|
|
217
|
+
this.validate(valueN);
|
|
218
|
+
|
|
219
|
+
return this.doForward(valueN);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Validate that a value is within the domain, do the work of transforming it forward, and apply a callback.
|
|
224
|
+
*
|
|
225
|
+
* @param transformerCallback
|
|
226
|
+
* Called after each value is transformed to convert it to its final value.
|
|
227
|
+
*
|
|
228
|
+
* @param value
|
|
229
|
+
* Value.
|
|
230
|
+
*
|
|
231
|
+
* @param index
|
|
232
|
+
* Index in sequence (0 for single transformation).
|
|
233
|
+
*
|
|
234
|
+
* @returns
|
|
235
|
+
* Transformed value.
|
|
236
|
+
*/
|
|
237
|
+
private validateDoForwardCallback<TOutput>(transformerCallback: TransformerCallback<bigint, TOutput>, value: number | bigint, index: number): TOutput {
|
|
238
|
+
return transformerCallback(this.validateDoForward(value), index);
|
|
239
|
+
};
|
|
240
|
+
|
|
194
241
|
/**
|
|
195
242
|
* Transform value(s) forward.
|
|
196
243
|
*
|
|
197
|
-
* @template
|
|
244
|
+
* @template TTransformerInput
|
|
198
245
|
* Value(s) input type.
|
|
199
246
|
*
|
|
200
247
|
* @param valueOrValues
|
|
201
|
-
* Value(s). If this is an instance of {@link
|
|
248
|
+
* Value(s). If this is an instance of {@link Sequence}, the minimum and maximum values are validated prior to
|
|
202
249
|
* transformation. Otherwise, the individual value(s) is/are validated at the time of transformation.
|
|
203
250
|
*
|
|
204
251
|
* @returns
|
|
205
252
|
* Transformed value(s).
|
|
206
253
|
*/
|
|
207
|
-
forward<
|
|
254
|
+
forward<TTransformerInput extends TransformerInput<number | bigint>>(valueOrValues: TTransformerInput): TransformerOutput<TTransformerInput, bigint>;
|
|
208
255
|
|
|
209
256
|
/**
|
|
210
257
|
* Transform value(s) forward, optionally applying a transformation.
|
|
211
258
|
*
|
|
212
|
-
* @template
|
|
259
|
+
* @template TTransformerInput
|
|
213
260
|
* Value(s) input type.
|
|
214
261
|
*
|
|
215
|
-
* @template
|
|
262
|
+
* @template TOutput
|
|
216
263
|
* Transformation callback output type.
|
|
217
264
|
*
|
|
218
265
|
* @param valueOrValues
|
|
219
|
-
* Value(s). If this is an instance of {@link
|
|
266
|
+
* Value(s). If this is an instance of {@link Sequence}, the minimum and maximum values are validated prior to
|
|
220
267
|
* transformation. Otherwise, the individual value(s) is/are validated at the time of transformation.
|
|
221
268
|
*
|
|
222
269
|
* @param transformerCallback
|
|
@@ -225,62 +272,36 @@ export abstract class Transformer {
|
|
|
225
272
|
* @returns
|
|
226
273
|
* Transformed value(s).
|
|
227
274
|
*/
|
|
228
|
-
forward<
|
|
275
|
+
forward<TTransformerInput extends TransformerInput<number | bigint>, TOutput>(valueOrValues: TTransformerInput, transformerCallback: TransformerCallback<bigint, TOutput>): TransformerOutput<TTransformerInput, TOutput>;
|
|
229
276
|
|
|
230
277
|
// eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
|
|
231
|
-
forward<
|
|
278
|
+
forward<TTransformerInput extends TransformerInput<number | bigint>, TOutput>(valueOrValues: TTransformerInput, transformerCallback?: TransformerCallback<bigint, TOutput>): TransformerOutput<TTransformerInput, TOutput> {
|
|
232
279
|
// TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
|
|
233
|
-
let result: bigint |
|
|
280
|
+
let result: bigint | TOutput | Iterable<bigint> | Iterable<TOutput>;
|
|
234
281
|
|
|
235
282
|
if (typeof valueOrValues !== "object") {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
result = transformerCallback === undefined ? transformedValue : transformerCallback(transformedValue, 0);
|
|
243
|
-
} else if (valueOrValues instanceof Sequencer) {
|
|
244
|
-
if (valueOrValues.minValue < 0n) {
|
|
245
|
-
throw new RangeError(i18nextUtility.t("Transformer.minValueMustBeGreaterThanOrEqualToZero", {
|
|
246
|
-
minValue: valueOrValues.minValue
|
|
283
|
+
result = transformerCallback === undefined ? this.validateDoForward(valueOrValues) : this.validateDoForwardCallback(transformerCallback, valueOrValues, 0);
|
|
284
|
+
} else if (valueOrValues instanceof Sequence) {
|
|
285
|
+
if (valueOrValues.minimumValue < 0n) {
|
|
286
|
+
throw new RangeError(i18nextUtility.t("Transformer.minimumValueMustBeGreaterThanOrEqualToZero", {
|
|
287
|
+
minimumValue: valueOrValues.minimumValue
|
|
247
288
|
}));
|
|
248
289
|
}
|
|
249
290
|
|
|
250
|
-
if (valueOrValues.
|
|
251
|
-
throw new RangeError(i18nextUtility.t("Transformer.
|
|
252
|
-
|
|
291
|
+
if (valueOrValues.maximumValue >= this.domain) {
|
|
292
|
+
throw new RangeError(i18nextUtility.t("Transformer.maximumValueMustBeLessThan", {
|
|
293
|
+
maximumValue: valueOrValues.maximumValue,
|
|
253
294
|
domain: this.domain
|
|
254
295
|
}));
|
|
255
296
|
}
|
|
256
297
|
|
|
257
|
-
|
|
258
|
-
result = transformIterable(valueOrValues, value => this.doForward(value));
|
|
259
|
-
} else {
|
|
260
|
-
result = transformIterable(valueOrValues, (value, index) => transformerCallback(this.doForward(value), index));
|
|
261
|
-
}
|
|
298
|
+
result = transformerCallback === undefined ? transformIterable(valueOrValues, value => this.doForward(value)) : transformIterable(valueOrValues, (value, index) => transformerCallback(this.doForward(value), index));
|
|
262
299
|
} else {
|
|
263
|
-
|
|
264
|
-
result = transformIterable(valueOrValues, (value) => {
|
|
265
|
-
const valueN = BigInt(value);
|
|
266
|
-
|
|
267
|
-
this.validate(valueN);
|
|
268
|
-
|
|
269
|
-
return this.doForward(valueN);
|
|
270
|
-
});
|
|
271
|
-
} else {
|
|
272
|
-
result = transformIterable(valueOrValues, (value, index) => {
|
|
273
|
-
const valueN = BigInt(value);
|
|
274
|
-
|
|
275
|
-
this.validate(valueN);
|
|
276
|
-
|
|
277
|
-
return transformerCallback(this.doForward(valueN), index);
|
|
278
|
-
});
|
|
279
|
-
}
|
|
300
|
+
result = transformerCallback === undefined ? transformIterable(valueOrValues, value => this.validateDoForward(value)) : transformIterable(valueOrValues, (value, index) => this.validateDoForwardCallback(transformerCallback, value, index));
|
|
280
301
|
}
|
|
281
302
|
|
|
282
303
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
|
|
283
|
-
return result as TransformerOutput<
|
|
304
|
+
return result as TransformerOutput<TTransformerInput, TOutput>;
|
|
284
305
|
}
|
|
285
306
|
|
|
286
307
|
/**
|
|
@@ -332,10 +353,11 @@ export class IdentityTransformer extends Transformer {
|
|
|
332
353
|
}
|
|
333
354
|
|
|
334
355
|
/**
|
|
335
|
-
* Encryption transformer. Values are transformed using repeated shuffle and xor operations
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
356
|
+
* Encryption transformer. Values are transformed using repeated shuffle and xor operations, similar to those found in
|
|
357
|
+
* many cryptography algorithms, particularly AES. While sufficient for obfuscation of numeric sequences (e.g., serial
|
|
358
|
+
* number generation, below), if true format-preserving encryption is required, a more robust algorithm such as
|
|
359
|
+
* {@link https://doi.org/10.6028/NIST.SP.800-38Gr1-draft | FF1} is recommended. Furthermore, no work has been done to
|
|
360
|
+
* mitigate {@link https://timing.attacks.cr.yp.to/index.html | timing attacks} for key detection.
|
|
339
361
|
*
|
|
340
362
|
* The purpose of the encryption transformer is to generate pseudo-random values in a deterministic manner to obscure
|
|
341
363
|
* the sequence of values generated over time. A typical example is for serial number generation, where knowledge of the
|
|
@@ -371,11 +393,6 @@ export class EncryptionTransformer extends Transformer {
|
|
|
371
393
|
*/
|
|
372
394
|
private readonly _domainBytes: number;
|
|
373
395
|
|
|
374
|
-
/**
|
|
375
|
-
* Tweak.
|
|
376
|
-
*/
|
|
377
|
-
private readonly _tweak: bigint;
|
|
378
|
-
|
|
379
396
|
/**
|
|
380
397
|
* Xor bytes array generated from the domain and tweak.
|
|
381
398
|
*/
|
|
@@ -417,26 +434,23 @@ export class EncryptionTransformer extends Transformer {
|
|
|
417
434
|
let domainBytes = 0;
|
|
418
435
|
|
|
419
436
|
// The number of bytes in the domain determines the size of the shuffle and xor operations.
|
|
420
|
-
for (let reducedDomainMinusOne = this.domain - 1n; reducedDomainMinusOne !== 0n; reducedDomainMinusOne
|
|
437
|
+
for (let reducedDomainMinusOne = this.domain - 1n; reducedDomainMinusOne !== 0n; reducedDomainMinusOne >>= 8n) {
|
|
421
438
|
domainBytes++;
|
|
422
439
|
}
|
|
423
440
|
|
|
424
441
|
this._domainBytes = domainBytes;
|
|
425
|
-
this._tweak = BigInt(tweak);
|
|
426
442
|
|
|
427
443
|
const xorBytes = new Array<number>();
|
|
428
444
|
const bits = new Array<number>();
|
|
429
445
|
const inverseBits = new Array<number>();
|
|
430
446
|
|
|
431
447
|
// Key is the product of domain, tweak, and an 8-digit prime to force at least four rounds.
|
|
432
|
-
for (let reducedKey = this.domain *
|
|
433
|
-
// Extract least
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
xorBytes.unshift(keyByte);
|
|
448
|
+
for (let reducedKey = this.domain * BigInt(tweak) * 603868999n; reducedKey !== 0n; reducedKey >>= 8n) {
|
|
449
|
+
// Extract the least significant byte.
|
|
450
|
+
xorBytes.unshift(Number(BigInt.asUintN(8, reducedKey)));
|
|
437
451
|
|
|
438
|
-
// Bit number is the key
|
|
439
|
-
const bitNumber =
|
|
452
|
+
// Bit number is the reduced key mod 8.
|
|
453
|
+
const bitNumber = Number(BigInt.asUintN(3, reducedKey));
|
|
440
454
|
|
|
441
455
|
// Bits are applied in reverse order so that they don't correlate directly with the key bytes at the same index.
|
|
442
456
|
bits.push(EncryptionTransformer.BITS[bitNumber]);
|
|
@@ -465,13 +479,6 @@ export class EncryptionTransformer extends Transformer {
|
|
|
465
479
|
}
|
|
466
480
|
}
|
|
467
481
|
|
|
468
|
-
/**
|
|
469
|
-
* Get the tweak.
|
|
470
|
-
*/
|
|
471
|
-
get tweak(): bigint {
|
|
472
|
-
return this._tweak;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
482
|
/**
|
|
476
483
|
* Convert a value to a byte array big enough to handle the entire domain.
|
|
477
484
|
*
|
|
@@ -484,13 +491,9 @@ export class EncryptionTransformer extends Transformer {
|
|
|
484
491
|
private valueToBytes(value: bigint): Uint8Array {
|
|
485
492
|
const bytes = new Uint8Array(this._domainBytes);
|
|
486
493
|
|
|
487
|
-
let reducedValue = value;
|
|
488
|
-
|
|
489
494
|
// Build byte array in reverse order to get as big-endian.
|
|
490
|
-
for (let index = this._domainBytes - 1; index >= 0; index
|
|
491
|
-
bytes[index] = Number(reducedValue
|
|
492
|
-
|
|
493
|
-
reducedValue = reducedValue >> 8n;
|
|
495
|
+
for (let index = this._domainBytes - 1, reducedValue = value; index >= 0 && reducedValue !== 0n; index--, reducedValue >>= 8n) {
|
|
496
|
+
bytes[index] = Number(BigInt.asUintN(8, reducedValue));
|
|
494
497
|
}
|
|
495
498
|
|
|
496
499
|
return bytes;
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
HEXADECIMAL_CREATOR,
|
|
9
9
|
i18nUtilityInit,
|
|
10
10
|
NUMERIC_CREATOR,
|
|
11
|
-
|
|
11
|
+
Sequence
|
|
12
12
|
} from "../src/index.js";
|
|
13
13
|
|
|
14
14
|
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
@@ -65,7 +65,7 @@ function testCharacterSetCreator(name: string, characterSetCreator: CharacterSet
|
|
|
65
65
|
break;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const sequence = Iterator.from(characterSetCreator.create(length, new
|
|
68
|
+
const sequence = Iterator.from(characterSetCreator.create(length, new Sequence(0n, domain), exclusion));
|
|
69
69
|
|
|
70
70
|
let previousS = "";
|
|
71
71
|
|
|
@@ -86,7 +86,7 @@ function testCharacterSetCreator(name: string, characterSetCreator: CharacterSet
|
|
|
86
86
|
|
|
87
87
|
expect(() => characterSetCreator.create(length, domain, exclusion)).toThrow(`Value ${domain} must be less than ${domain}`);
|
|
88
88
|
|
|
89
|
-
const sparseSequence = Iterator.from(characterSetCreator.create(length, new
|
|
89
|
+
const sparseSequence = Iterator.from(characterSetCreator.create(length, new Sequence(domain - 1, -domain), exclusion, 123456n));
|
|
90
90
|
|
|
91
91
|
let sequential = true;
|
|
92
92
|
previousS = "~";
|
|
@@ -96,7 +96,7 @@ function testCharacterSetCreator(name: string, characterSetCreator: CharacterSet
|
|
|
96
96
|
sequenceCount = 0;
|
|
97
97
|
|
|
98
98
|
sparseSequence.forEach((s, index) => {
|
|
99
|
-
sequential
|
|
99
|
+
sequential &&= s < previousS;
|
|
100
100
|
previousS = s;
|
|
101
101
|
|
|
102
102
|
expect(s.length).toBe(length);
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
|
-
import { i18nUtilityInit,
|
|
3
|
+
import { i18nUtilityInit, Sequence } from "../src/index.js";
|
|
4
4
|
|
|
5
5
|
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
6
6
|
|
|
7
7
|
describe("Sequence", () => {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const sequence1 = new Sequence(10, 20);
|
|
9
|
+
const sequence2 = new Sequence(29, -20);
|
|
10
10
|
|
|
11
11
|
test("Structure", () => {
|
|
12
|
-
expect(
|
|
13
|
-
expect(
|
|
14
|
-
expect(
|
|
15
|
-
expect(
|
|
16
|
-
expect(
|
|
17
|
-
|
|
18
|
-
expect(
|
|
19
|
-
expect(
|
|
20
|
-
expect(
|
|
21
|
-
expect(
|
|
22
|
-
expect(
|
|
12
|
+
expect(sequence1.startValue).toBe(10n);
|
|
13
|
+
expect(sequence1.endValue).toBe(30n);
|
|
14
|
+
expect(sequence1.count).toBe(20);
|
|
15
|
+
expect(sequence1.minimumValue).toBe(10n);
|
|
16
|
+
expect(sequence1.maximumValue).toBe(29n);
|
|
17
|
+
|
|
18
|
+
expect(sequence2.startValue).toBe(29n);
|
|
19
|
+
expect(sequence2.endValue).toBe(9n);
|
|
20
|
+
expect(sequence2.count).toBe(-20);
|
|
21
|
+
expect(sequence2.minimumValue).toBe(10n);
|
|
22
|
+
expect(sequence2.maximumValue).toBe(29n);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
function iterate(): void {
|
|
@@ -29,7 +29,7 @@ describe("Sequence", () => {
|
|
|
29
29
|
expectedValue = 10n;
|
|
30
30
|
count = 0;
|
|
31
31
|
|
|
32
|
-
for (const value of Iterator.from(
|
|
32
|
+
for (const value of Iterator.from(sequence1)) {
|
|
33
33
|
expect(value).toBe(expectedValue);
|
|
34
34
|
|
|
35
35
|
expectedValue++;
|
|
@@ -41,7 +41,7 @@ describe("Sequence", () => {
|
|
|
41
41
|
expectedValue = 29n;
|
|
42
42
|
count = 0;
|
|
43
43
|
|
|
44
|
-
for (const value of Iterator.from(
|
|
44
|
+
for (const value of Iterator.from(sequence2)) {
|
|
45
45
|
expect(value).toBe(expectedValue);
|
|
46
46
|
|
|
47
47
|
expectedValue--;
|
package/test/transformer.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
|
-
import { EncryptionTransformer, i18nUtilityInit, IdentityTransformer,
|
|
3
|
+
import { EncryptionTransformer, i18nUtilityInit, IdentityTransformer, Sequence, Transformer } from "../src/index.js";
|
|
4
4
|
|
|
5
5
|
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ function testTransformer(domain: number, tweak?: number, callback?: (value: bigi
|
|
|
11
11
|
|
|
12
12
|
const transformedValuesSet = new Set<bigint>();
|
|
13
13
|
|
|
14
|
-
Iterator.from(transformer.forward(new
|
|
14
|
+
Iterator.from(transformer.forward(new Sequence(0n, domain))).forEach((transformedValue, index) => {
|
|
15
15
|
const indexN = BigInt(index);
|
|
16
16
|
|
|
17
17
|
if (sequential && transformedValue !== indexN) {
|
|
@@ -43,11 +43,11 @@ function testTransformer(domain: number, tweak?: number, callback?: (value: bigi
|
|
|
43
43
|
expect(Array.from(transformer.forward(randomValues))).toStrictEqual(transformedRandomValues);
|
|
44
44
|
|
|
45
45
|
expect(() => transformer.forward(domain)).toThrow(`Value ${domain} must be less than ${domain}`);
|
|
46
|
-
expect(() => transformer.forward(new
|
|
47
|
-
expect(() => transformer.forward(new
|
|
48
|
-
expect(() => transformer.forward(new
|
|
49
|
-
expect(() => transformer.forward(new
|
|
50
|
-
expect(() => transformer.forward(new
|
|
46
|
+
expect(() => transformer.forward(new Sequence(domain, 0))).not.toThrow(RangeError);
|
|
47
|
+
expect(() => transformer.forward(new Sequence(domain - 1, 1))).not.toThrow(RangeError);
|
|
48
|
+
expect(() => transformer.forward(new Sequence(domain, 1))).toThrow(`Maximum value ${domain} must be less than ${domain}`);
|
|
49
|
+
expect(() => transformer.forward(new Sequence(0, -1))).not.toThrow(RangeError);
|
|
50
|
+
expect(() => transformer.forward(new Sequence(-1, -1))).toThrow("Minimum value -1 must be greater than or equal to 0");
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
describe("Identity", () => {
|
|
@@ -83,7 +83,6 @@ describe("Encryption", () => {
|
|
|
83
83
|
expect(Transformer.get(1000n, 1234n)).toBe(transformer);
|
|
84
84
|
|
|
85
85
|
expect(transformer.domain).toBe(BigInt(1000n));
|
|
86
|
-
expect((transformer as EncryptionTransformer).tweak).toBe(BigInt(1234n));
|
|
87
86
|
|
|
88
87
|
const transformer0 = Transformer.get(1000, 0);
|
|
89
88
|
|
|
@@ -129,7 +128,7 @@ describe("Encryption", () => {
|
|
|
129
128
|
});
|
|
130
129
|
|
|
131
130
|
test("Tweak variation", () => {
|
|
132
|
-
expect(Array.from(Transformer.get(1000, 1235).forward(new
|
|
131
|
+
expect(Array.from(Transformer.get(1000, 1235).forward(new Sequence(0n, 1000)))).not.toStrictEqual(Array.from(Transformer.get(1000, 1234).forward(new Sequence(0n, 1000))));
|
|
133
132
|
});
|
|
134
133
|
|
|
135
134
|
test("Consistency", () => {
|
|
@@ -140,30 +139,30 @@ describe("Encryption", () => {
|
|
|
140
139
|
});
|
|
141
140
|
});
|
|
142
141
|
|
|
143
|
-
describe("Non-
|
|
144
|
-
function testIterables(
|
|
145
|
-
const
|
|
142
|
+
describe("Non-sequence", () => {
|
|
143
|
+
function testIterables(sequence: Sequence): void {
|
|
144
|
+
const nonSequence = Array.from(sequence);
|
|
146
145
|
|
|
147
146
|
const transformer = Transformer.get(1000n, 1234n);
|
|
148
147
|
|
|
149
|
-
const
|
|
150
|
-
const
|
|
148
|
+
const sequenceForward = transformer.forward(sequence);
|
|
149
|
+
const nonSequenceForward = transformer.forward(nonSequence);
|
|
151
150
|
|
|
152
|
-
const
|
|
151
|
+
const nonSequenceIterator = nonSequenceForward[Symbol.iterator]();
|
|
153
152
|
|
|
154
|
-
for (const
|
|
155
|
-
const
|
|
153
|
+
for (const sequenceValue of sequenceForward) {
|
|
154
|
+
const nonSequenceNext = nonSequenceIterator.next();
|
|
156
155
|
|
|
157
|
-
expect(
|
|
158
|
-
expect(
|
|
156
|
+
expect(nonSequenceNext.done).not.toBe(true);
|
|
157
|
+
expect(nonSequenceNext.value).toBe(sequenceValue);
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
160
|
|
|
162
161
|
test("Ascending", () => {
|
|
163
|
-
testIterables(new
|
|
162
|
+
testIterables(new Sequence(0, 10));
|
|
164
163
|
});
|
|
165
164
|
|
|
166
165
|
test("Descending", () => {
|
|
167
|
-
testIterables(new
|
|
166
|
+
testIterables(new Sequence(9, -10));
|
|
168
167
|
});
|
|
169
168
|
});
|