@standen/encoding 0.0.1 → 0.0.2
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/main.ts +5 -0
- package/package.json +16 -21
- package/src/alphabet.ts +68 -0
- package/src/encoder.ts +70 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +40 -0
- package/README.md +0 -1
- package/index.js +0 -1
package/main.ts
ADDED
package/package.json
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@standen/encoding",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"main": "index.js",
|
|
18
|
-
"scripts": {
|
|
19
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@standen/encoding",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"main": "./src/index.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": "https://github.com/standen/encoding",
|
|
7
|
+
"author": "Standen",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"@types/node": "^25.3.0",
|
|
11
|
+
"typescript": "^5.9.3"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/src/alphabet.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const ALPHABET_EN = "abcdefghijklmnopqrstuvwxyz";
|
|
2
|
+
const ALPHABET_RU = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
|
|
3
|
+
|
|
4
|
+
type T_ALPABET = Readonly<{
|
|
5
|
+
digits: string;
|
|
6
|
+
enSmall: string;
|
|
7
|
+
enBig: string;
|
|
8
|
+
ruSmall: string;
|
|
9
|
+
ruBig: string;
|
|
10
|
+
specChars: string;
|
|
11
|
+
sugarChars: string;
|
|
12
|
+
}>;
|
|
13
|
+
|
|
14
|
+
const ALPHABET: T_ALPABET = {
|
|
15
|
+
digits: "0123456789",
|
|
16
|
+
enSmall: ALPHABET_EN,
|
|
17
|
+
enBig: ALPHABET_EN.toUpperCase(),
|
|
18
|
+
ruSmall: ALPHABET_RU,
|
|
19
|
+
ruBig: ALPHABET_RU.toUpperCase(),
|
|
20
|
+
specChars: "~`'\"!@#№$;:,^%&?*()-+=|\\<>[]{}._ ",
|
|
21
|
+
sugarChars:
|
|
22
|
+
"ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞ",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type T_MAPPED_ALPHABET = Partial<{
|
|
26
|
+
BYTES_TO_HEX: Map<number, string>;
|
|
27
|
+
HEX_TO_BYTES: Map<string, number>;
|
|
28
|
+
TEXT_TO_BYTES: Map<string, number>;
|
|
29
|
+
BYTES_TO_TEXT: Map<number, string>;
|
|
30
|
+
}>;
|
|
31
|
+
|
|
32
|
+
const ALL_SYMBOLS = Object.values(ALPHABET).join("").slice(0, 256);
|
|
33
|
+
|
|
34
|
+
const MAPPED_ALPHABET: T_MAPPED_ALPHABET = {};
|
|
35
|
+
|
|
36
|
+
MAPPED_ALPHABET.BYTES_TO_HEX = Array.from({ length: 256 }, (_, i) => i).reduce(
|
|
37
|
+
(acc: Map<number, string>, value) => {
|
|
38
|
+
acc.set(value, value.toString(16).padStart(2, "0"));
|
|
39
|
+
return acc;
|
|
40
|
+
},
|
|
41
|
+
new Map<number, string>()
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
MAPPED_ALPHABET.HEX_TO_BYTES = Array.from({ length: 256 }, (_, i) => i).reduce(
|
|
45
|
+
(acc: Map<string, number>, value) => {
|
|
46
|
+
acc.set(value.toString(16).padStart(2, "0"), value);
|
|
47
|
+
return acc;
|
|
48
|
+
},
|
|
49
|
+
new Map<string, number>()
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
MAPPED_ALPHABET.TEXT_TO_BYTES = ALL_SYMBOLS.split("").reduce(
|
|
53
|
+
(acc: Map<string, number>, value, index) => {
|
|
54
|
+
acc.set(value, index);
|
|
55
|
+
return acc;
|
|
56
|
+
},
|
|
57
|
+
new Map<string, number>()
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
MAPPED_ALPHABET.BYTES_TO_TEXT = ALL_SYMBOLS.split("").reduce(
|
|
61
|
+
(acc: Map<number, string>, value, index) => {
|
|
62
|
+
acc.set(index, value);
|
|
63
|
+
return acc;
|
|
64
|
+
},
|
|
65
|
+
new Map<number, string>()
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
export { ALPHABET, MAPPED_ALPHABET };
|
package/src/encoder.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ALPHABET, MAPPED_ALPHABET } from "./alphabet";
|
|
2
|
+
|
|
3
|
+
export class Encoder {
|
|
4
|
+
private readonly HEX_SYMBOLS = "0123456789abcdef";
|
|
5
|
+
|
|
6
|
+
public validateHex = (hex: string): boolean =>
|
|
7
|
+
hex.split("").every((item) => this.HEX_SYMBOLS.includes(item));
|
|
8
|
+
|
|
9
|
+
public validateText = (text: string): boolean =>
|
|
10
|
+
text
|
|
11
|
+
.split("")
|
|
12
|
+
.every((item) =>
|
|
13
|
+
Object.values(ALPHABET).join("").slice(0, 256).includes(item)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
private splitHexIntoPairs = (hex: string): string[] => {
|
|
17
|
+
if (hex.length % 2 !== 0) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
"Строка должна состоять из bytes в hex формате с ведущими нулями!"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return hex.match(/.{1,2}/g) || [];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
public bytesToHex = (bytes: Uint8Array): string =>
|
|
26
|
+
bytes.reduce((acc, value) => {
|
|
27
|
+
acc += MAPPED_ALPHABET.BYTES_TO_HEX?.get(value) || "";
|
|
28
|
+
return acc;
|
|
29
|
+
}, "");
|
|
30
|
+
|
|
31
|
+
public hexToBytes = (hex: string): Uint8Array => {
|
|
32
|
+
if (hex.length % 2 !== 0) {
|
|
33
|
+
throw new Error("Длина строки должна быть четной");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!this.validateHex(hex)) {
|
|
37
|
+
throw new Error("Строка должна содержать только hex символы");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const pairsString = this.splitHexIntoPairs(hex);
|
|
41
|
+
|
|
42
|
+
const bytes = new Uint8Array(pairsString.length);
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i <= bytes.length; i++) {
|
|
45
|
+
bytes[i] = MAPPED_ALPHABET.HEX_TO_BYTES?.get(pairsString[i]) || 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return bytes;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
public bytesToText = (bytes: Uint8Array): string =>
|
|
52
|
+
bytes.reduce((acc, value) => {
|
|
53
|
+
acc += MAPPED_ALPHABET.BYTES_TO_TEXT?.get(value) || "";
|
|
54
|
+
return acc;
|
|
55
|
+
}, "");
|
|
56
|
+
|
|
57
|
+
public textToBytes = (text: string): Uint8Array => {
|
|
58
|
+
if (!this.validateText(text)) {
|
|
59
|
+
throw new Error("Присутствуют недопустимые символы!");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const bytes = new Uint8Array(text.length);
|
|
63
|
+
|
|
64
|
+
for (let i = 0; i <= bytes.length; i++) {
|
|
65
|
+
bytes[i] = MAPPED_ALPHABET.TEXT_TO_BYTES?.get(text[i]) || 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return bytes;
|
|
69
|
+
};
|
|
70
|
+
}
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
/* Базовые настройки */
|
|
4
|
+
"target": "es2024",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"lib": ["es2024"],
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"rootDir": "./src",
|
|
12
|
+
"strict": true,
|
|
13
|
+
|
|
14
|
+
/* Дополнительные проверки */
|
|
15
|
+
"noUnusedLocals": true,
|
|
16
|
+
"noUnusedParameters": true,
|
|
17
|
+
"noImplicitReturns": true,
|
|
18
|
+
"noFallthroughCasesInSwitch": true,
|
|
19
|
+
|
|
20
|
+
/* Модульное разрешение */
|
|
21
|
+
"moduleResolution": "node",
|
|
22
|
+
"esModuleInterop": true,
|
|
23
|
+
"resolveJsonModule": true,
|
|
24
|
+
|
|
25
|
+
/* Экспериментальные настройки */
|
|
26
|
+
"experimentalDecorators": true,
|
|
27
|
+
"emitDecoratorMetadata": true,
|
|
28
|
+
|
|
29
|
+
/* Продвинутые настройки */
|
|
30
|
+
"forceConsistentCasingInFileNames": true,
|
|
31
|
+
"skipLibCheck": true
|
|
32
|
+
},
|
|
33
|
+
"include": ["src/**/*"],
|
|
34
|
+
"exclude": [
|
|
35
|
+
"node_modules",
|
|
36
|
+
"dist",
|
|
37
|
+
"**/*.test.ts",
|
|
38
|
+
"**/*.spec.ts"
|
|
39
|
+
]
|
|
40
|
+
}
|
package/README.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# encoding
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const test = "test";
|