sonic-ws 1.3.3 → 2.0.0-fix
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 +56 -196
- package/README.md +88 -17
- package/bundled/bundle.js +6 -0
- package/bundled/bundle.wasm +0 -0
- package/dist/{index.d.ts → ts/index.d.ts} +11 -0
- package/dist/{index.js → ts/index.js} +10 -11
- package/dist/ts/native/wrapper.d.ts +64 -0
- package/dist/ts/native/wrapper.js +7 -0
- package/dist/ts/version.d.ts +16 -0
- package/dist/ts/version.js +7 -0
- package/dist/{ws → ts/ws}/Connection.d.ts +10 -0
- package/dist/ts/ws/Connection.js +7 -0
- package/dist/{ws → ts/ws}/PacketProcessor.d.ts +10 -0
- package/dist/ts/ws/PacketProcessor.js +7 -0
- package/dist/{ws → ts/ws}/client/core/ClientCore.d.ts +10 -0
- package/dist/ts/ws/client/core/ClientCore.js +7 -0
- package/dist/{ws → ts/ws}/client/node/ClientNode.d.ts +10 -0
- package/dist/ts/ws/client/node/ClientNode.js +7 -0
- package/dist/ts/ws/debug/DebugServer.d.ts +17 -0
- package/dist/ts/ws/debug/DebugServer.js +7 -0
- package/dist/{ws → ts/ws}/packets/PacketType.d.ts +11 -1
- package/dist/ts/ws/packets/PacketType.js +7 -0
- package/dist/{ws → ts/ws}/packets/Packets.d.ts +10 -3
- package/dist/ts/ws/packets/Packets.js +7 -0
- package/dist/{ws → ts/ws}/server/SonicWSConnection.d.ts +10 -0
- package/dist/ts/ws/server/SonicWSConnection.js +7 -0
- package/dist/{ws → ts/ws}/server/SonicWSServer.d.ts +13 -0
- package/dist/ts/ws/server/SonicWSServer.js +7 -0
- package/dist/{ws → ts/ws}/util/BufferUtil.d.ts +10 -0
- package/dist/ts/ws/util/BufferUtil.js +7 -0
- package/dist/ts/ws/util/StringUtil.d.ts +13 -0
- package/dist/ts/ws/util/StringUtil.js +7 -0
- package/dist/{ws → ts/ws}/util/enums/EnumHandler.d.ts +10 -0
- package/dist/ts/ws/util/enums/EnumHandler.js +7 -0
- package/dist/ts/ws/util/enums/EnumType.d.ts +12 -0
- package/dist/ts/ws/util/enums/EnumType.js +7 -0
- package/dist/ts/ws/util/packets/BatchHelper.d.ts +11 -0
- package/dist/ts/ws/util/packets/BatchHelper.js +7 -0
- package/dist/ts/ws/util/packets/CompressionUtil.d.ts +18 -0
- package/dist/ts/ws/util/packets/CompressionUtil.js +7 -0
- package/dist/ts/ws/util/packets/HashUtil.d.ts +12 -0
- package/dist/ts/ws/util/packets/HashUtil.js +7 -0
- package/dist/ts/ws/util/packets/JSONUtil.d.ts +12 -0
- package/dist/ts/ws/util/packets/JSONUtil.js +7 -0
- package/dist/ts/ws/util/packets/PacketHolder.d.ts +11 -0
- package/dist/ts/ws/util/packets/PacketHolder.js +7 -0
- package/dist/{ws → ts/ws}/util/packets/PacketUtils.d.ts +10 -0
- package/dist/ts/ws/util/packets/PacketUtils.js +7 -0
- package/dist/ts/ws/util/packets/RateHandler.d.ts +11 -0
- package/dist/ts/ws/util/packets/RateHandler.js +7 -0
- package/package.json +14 -10
- package/dist/version.d.ts +0 -6
- package/dist/version.js +0 -25
- package/dist/ws/Connection.js +0 -126
- package/dist/ws/PacketProcessor.js +0 -52
- package/dist/ws/client/core/ClientCore.js +0 -251
- package/dist/ws/client/node/ClientNode.js +0 -36
- package/dist/ws/debug/DebugServer.d.ts +0 -7
- package/dist/ws/debug/DebugServer.js +0 -607
- package/dist/ws/packets/PacketProcessors.d.ts +0 -13
- package/dist/ws/packets/PacketProcessors.js +0 -317
- package/dist/ws/packets/PacketType.js +0 -61
- package/dist/ws/packets/Packets.js +0 -277
- package/dist/ws/server/SonicWSConnection.js +0 -298
- package/dist/ws/server/SonicWSServer.js +0 -307
- package/dist/ws/util/BufferUtil.js +0 -42
- package/dist/ws/util/StringUtil.d.ts +0 -5
- package/dist/ws/util/StringUtil.js +0 -51
- package/dist/ws/util/enums/EnumHandler.js +0 -60
- package/dist/ws/util/enums/EnumType.d.ts +0 -2
- package/dist/ws/util/enums/EnumType.js +0 -72
- package/dist/ws/util/packets/BatchHelper.d.ts +0 -1
- package/dist/ws/util/packets/BatchHelper.js +0 -85
- package/dist/ws/util/packets/CompressionUtil.d.ts +0 -35
- package/dist/ws/util/packets/CompressionUtil.js +0 -277
- package/dist/ws/util/packets/HashUtil.d.ts +0 -2
- package/dist/ws/util/packets/HashUtil.js +0 -122
- package/dist/ws/util/packets/JSONUtil.d.ts +0 -2
- package/dist/ws/util/packets/JSONUtil.js +0 -179
- package/dist/ws/util/packets/PacketHolder.d.ts +0 -1
- package/dist/ws/util/packets/PacketHolder.js +0 -126
- package/dist/ws/util/packets/PacketUtils.js +0 -283
- package/dist/ws/util/packets/RateHandler.d.ts +0 -1
- package/dist/ws/util/packets/RateHandler.js +0 -66
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2026 Lily (liwybloc)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.processCharCodes = processCharCodes;
|
|
19
|
-
exports.convertCharCodes = convertCharCodes;
|
|
20
|
-
exports.encodeHuffman = encodeHuffman;
|
|
21
|
-
exports.decodeHuffman = decodeHuffman;
|
|
22
|
-
exports.as8String = as8String;
|
|
23
|
-
const CompressionUtil_1 = require("./packets/CompressionUtil");
|
|
24
|
-
function processCharCodes(text) {
|
|
25
|
-
return Array.from(text, char => char.codePointAt(0));
|
|
26
|
-
}
|
|
27
|
-
function convertCharCodes(codes) {
|
|
28
|
-
return String.fromCodePoint(...codes);
|
|
29
|
-
}
|
|
30
|
-
const codeToChar = { "1000001": "w", "1000010": "m", "1000100": "u", "1000101": "c", "1000110": "l", "1000111": "d", "1001001": "r", "1001010": "h", "1001100": "s", "1001101": "n", "1001110": "i", "1001111": "o", "1010001": "a", "1010010": "t", "1010100": "e", "1010101": "", "10000000": "", "10000001": "", "10000111": "", "10010000": "
", "10010001": "", "10010111": "", "10100000": "", "10100001": "", "10100111": "", "10101100": "", "10101101": "~", "10101111": "}", "10110000": "|", "10110001": "{", "10110011": "`", "10110100": "_", "10110101": "^", "10110111": "]", "10111000": "", "10111001": "[", "10111011": "@", "10111100": "?", "10111101": ">", "10111111": "=", "11000000": "<", "11000001": ";", "11000011": ":", "11000100": "9", "11000101": "8", "11000111": "7", "11001000": "6", "11001001": "5", "11001011": "4", "11001100": "3", "11001101": "2", "11001111": "1", "11010000": "0", "11010001": "/", "11010011": ".", "11010100": "-", "11010101": ",", "11010111": "+", "11011000": "*", "11011001": ")", "11011011": "(", "11011100": "'", "11011101": "&", "11011111": "$", "11100001": "#", "11100010": "\"", "11100100": "!", "11100101": "\u001f", "11100110": "\u001e", "11100111": "\u001d", "11101001": "\u001c", "11101010": "\u001b", "11101100": "\u001a", "11101101": "\u0019", "11101110": "\u0018", "11101111": "\u0017", "11110001": "\u0016", "11110010": "\u0015", "11110100": "\u0014", "11110101": "\u0013", "11110110": "\u0012", "11110111": "\u0011", "11111001": "\u0010", "11111010": "\u000f", "11111100": "\u000e", "11111101": "", "11111110": "", "11111111": "", "100001100": "Ã", "100101100": "Â", "100101101": "Á", "101001100": "À", "101011100": "¿", "101011101": "¾", "101100100": "½", "101101100": "¼", "101101101": "»", "101110100": "º", "101111100": "¹", "101111101": "¸", "110000100": "·", "110001100": "¶", "110001101": "µ", "110010100": "´", "110011100": "³", "110011101": "²", "110100100": "±", "110101100": "°", "110101101": "¯", "110110100": "®", "110111100": "", "110111101": "%", "111000000": "¬", "111000001": "«", "111000111": "ª", "111010000": "©", "111010001": "¨", "111010111": "§", "111100000": "¦", "111100001": "¥", "111100111": "¤", "111110000": "£", "111110001": "¢", "111110111": "¡", "1000011010": "á", "1010011010": "à", "1010011011": "ß", "1011001010": "Þ", "1011101010": "Ý", "1011101011": "Ü", "1100001010": "Û", "1100101010": "Ú", "1100101011": "Ù", "1101001010": "Ø", "1101101010": "×", "1101101011": "Ö", "1110001100": "Õ", "1110101100": "Ô", "1110101101": "Ó", "1111001100": "Ò", "1111101100": "Ñ", "1111101101": "Ð", "00000000": " ", "00000001": "", "0000001": "\n", "0000010": "", "000001100": "Ï", "0000011010": "ç", "00000110110": "ó", "000001101110": "ù", "0000011011110": "ü", "00000110111110": "þ", "00000110111111": "ý", "00000111": "", "0000100": "\b", "0000101": "\u0007", "0000110": "\u0006", "0000111": "\u0005", "00010000": "", "00010001": "", "0001001": "\u0004", "0001010": "\u0003", "000101100": "Î", "000101101": "Í", "00010111": "", "0001100": "\u0002", "0001101": "\u0001", "0001110": "", "0001111": "Z", "00100000": "", "00100001": "", "0010001": "Q", "0010010": "X", "001001100": "Ì", "0010011010": "æ", "0010011011": "å", "00100111": "", "0010100": "J", "0010101": "K", "0010110": "V", "0010111": "B", "00110000": "", "00110001": "", "0011001": "P", "0011010": "Y", "001101100": "Ë", "001101101": "Ê", "00110111": "", "0011100": "G", "0011101": "F", "0011110": "W", "0011111": "M", "01000000": "", "01000001": "", "0100001": "U", "0100010": "C", "010001100": "É", "0100011010": "ä", "01000110110": "ò", "01000110111": "ñ", "01000111": "", "0100100": "L", "0100101": "D", "0100110": "R", "0100111": "H", "01010000": "", "01010001": "", "0101001": "S", "0101010": "N", "010101100": "È", "010101101": "Ç", "01010111": "", "0101100": "I", "0101101": "O", "0101110": "A", "0101111": "T", "01100000": "", "01100001": "", "0110001": "E", "0110010": "z", "011001100": "Æ", "0110011010": "ã", "0110011011": "â", "01100111": "", "0110100": "q", "0110101": "x", "0110110": "j", "0110111": "k", "01110000": "", "01110001": "", "0111001": "v", "0111010": "b", "011101100": "Å", "011101101": "Ä", "01110111": "", "0111100": "p", "0111101": "y", "0111110": "g", "0111111": "f", "10000110110": "ð", "100001101110": "ø", "100001101111": "÷", "10110010110": "ï", "10110010111": "î", "11000010110": "í", "110000101110": "ö", "1100001011110": "û", "1100001011111": "ú", "11010010110": "ì", "11010010111": "ë", "11100011010": "ê", "111000110110": "õ", "111000110111": "ô", "11110011010": "é", "11110011011": "è" };
|
|
31
|
-
const charToCode = Object.fromEntries(Object.entries(codeToChar).map(([code, char]) => [char, code]));
|
|
32
|
-
function encodeHuffman(text) {
|
|
33
|
-
return (0, CompressionUtil_1.bitsToBytes)(Array.from(text).map(char => charToCode[char]).join(""));
|
|
34
|
-
}
|
|
35
|
-
;
|
|
36
|
-
function decodeHuffman(bits) {
|
|
37
|
-
let result = '';
|
|
38
|
-
let buffer = '';
|
|
39
|
-
for (const bit of bits) {
|
|
40
|
-
buffer += bit;
|
|
41
|
-
if (codeToChar[buffer]) {
|
|
42
|
-
result += codeToChar[buffer];
|
|
43
|
-
buffer = '';
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
;
|
|
49
|
-
function as8String(data) {
|
|
50
|
-
return convertCharCodes(Array.from(data));
|
|
51
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2026 Lily (liwybloc)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.SET_PACKAGES = exports.ENUM_KEY_TO_TAG = exports.ENUM_TAG_TO_KEY = exports.MAX_ENUM_SIZE = void 0;
|
|
19
|
-
exports.DefineEnum = DefineEnum;
|
|
20
|
-
exports.WrapEnum = WrapEnum;
|
|
21
|
-
exports.DeWrapEnum = DeWrapEnum;
|
|
22
|
-
const CompressionUtil_1 = require("../packets/CompressionUtil");
|
|
23
|
-
const EnumType_1 = require("./EnumType");
|
|
24
|
-
exports.MAX_ENUM_SIZE = CompressionUtil_1.MAX_BYTE;
|
|
25
|
-
exports.ENUM_TAG_TO_KEY = {};
|
|
26
|
-
exports.ENUM_KEY_TO_TAG = {};
|
|
27
|
-
exports.SET_PACKAGES = {};
|
|
28
|
-
/**
|
|
29
|
-
* Defines an enum with its tag and values
|
|
30
|
-
* @param tag The tag of the enum; used for WrapEnum(tag, ...)
|
|
31
|
-
* @param values The possible values of the enum
|
|
32
|
-
* @returns A packaged enum
|
|
33
|
-
*/
|
|
34
|
-
function DefineEnum(tag, values) {
|
|
35
|
-
const setPkg = exports.SET_PACKAGES[tag];
|
|
36
|
-
if (setPkg) {
|
|
37
|
-
if (setPkg.values.find((n, i) => values[i] != n))
|
|
38
|
-
throw new Error(`Pre-existing enum package of tag '${tag}' is set and different!`);
|
|
39
|
-
return setPkg;
|
|
40
|
-
}
|
|
41
|
-
if (values.length > exports.MAX_ENUM_SIZE)
|
|
42
|
-
throw new Error(`An enum can only hold ${exports.MAX_ENUM_SIZE} possible values.`);
|
|
43
|
-
exports.ENUM_TAG_TO_KEY[tag] = Object.fromEntries(values.map((v, i) => [v, i]));
|
|
44
|
-
exports.ENUM_KEY_TO_TAG[tag] = Object.fromEntries(values.map((v, i) => [i, v]));
|
|
45
|
-
return exports.SET_PACKAGES[tag] = new EnumType_1.EnumPackage(tag, values);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Wraps an enum into a transmittable format
|
|
49
|
-
* @param tag The tag of the enum
|
|
50
|
-
* @param value The value to send
|
|
51
|
-
* @returns A transmittable enum value
|
|
52
|
-
*/
|
|
53
|
-
function WrapEnum(tag, value) {
|
|
54
|
-
if (!(value in exports.ENUM_TAG_TO_KEY[tag]))
|
|
55
|
-
throw new Error(`Value "${value}" does not exist in enum "${tag}"`);
|
|
56
|
-
return exports.ENUM_TAG_TO_KEY[tag][value];
|
|
57
|
-
}
|
|
58
|
-
function DeWrapEnum(tag, value) {
|
|
59
|
-
return exports.ENUM_KEY_TO_TAG[tag][value];
|
|
60
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2026 Lily (liwybloc)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.EnumPackage = exports.TYPE_CONVERSION_MAP = void 0;
|
|
19
|
-
const StringUtil_1 = require("../StringUtil");
|
|
20
|
-
const EnumHandler_1 = require("./EnumHandler");
|
|
21
|
-
const TYPE_INDEX_MAP = {
|
|
22
|
-
'string': 0,
|
|
23
|
-
'number': 1,
|
|
24
|
-
'boolean': 2,
|
|
25
|
-
'undefined': 3,
|
|
26
|
-
'object': 4, // to handle null bug
|
|
27
|
-
};
|
|
28
|
-
exports.TYPE_CONVERSION_MAP = {
|
|
29
|
-
0: (d) => d,
|
|
30
|
-
1: (d) => parseFloat(d),
|
|
31
|
-
2: (d) => d == 'true',
|
|
32
|
-
3: () => undefined,
|
|
33
|
-
4: () => null,
|
|
34
|
-
};
|
|
35
|
-
function getTypedIndex(data) {
|
|
36
|
-
const type = typeof data;
|
|
37
|
-
if (!(type in TYPE_INDEX_MAP) && data != null)
|
|
38
|
-
throw new Error(`Cannot serialize type "${type}" in an enum!`);
|
|
39
|
-
return TYPE_INDEX_MAP[type];
|
|
40
|
-
}
|
|
41
|
-
/** @internal */
|
|
42
|
-
class EnumPackage {
|
|
43
|
-
tag;
|
|
44
|
-
values;
|
|
45
|
-
constructor(tag, values) {
|
|
46
|
-
this.tag = tag;
|
|
47
|
-
this.values = values;
|
|
48
|
-
this.wrap = this.wrap.bind(this);
|
|
49
|
-
}
|
|
50
|
-
serialize() {
|
|
51
|
-
const tag = (0, StringUtil_1.processCharCodes)(this.tag);
|
|
52
|
-
return [
|
|
53
|
-
this.tag.length, // tag length
|
|
54
|
-
...tag, // tag
|
|
55
|
-
this.values.length, // value count
|
|
56
|
-
...this.values.map(v => [
|
|
57
|
-
String(v).length, // value length
|
|
58
|
-
getTypedIndex(v), // value type
|
|
59
|
-
...(0, StringUtil_1.processCharCodes)(String(v)) // value
|
|
60
|
-
]).flat(),
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Wraps a value with this enum package
|
|
65
|
-
* @param value Value to wrap
|
|
66
|
-
* @returns Network encoded value
|
|
67
|
-
*/
|
|
68
|
-
wrap(value) {
|
|
69
|
-
return (0, EnumHandler_1.WrapEnum)(this.tag, value);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
exports.EnumPackage = EnumPackage;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2026 Lily (liwybloc)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.BatchHelper = void 0;
|
|
19
|
-
const BufferUtil_1 = require("../BufferUtil");
|
|
20
|
-
const CompressionUtil_1 = require("./CompressionUtil");
|
|
21
|
-
/** @internal */
|
|
22
|
-
class BatchHelper {
|
|
23
|
-
batchInfo = {};
|
|
24
|
-
batchTimeouts = {};
|
|
25
|
-
batchedData = {};
|
|
26
|
-
conn;
|
|
27
|
-
registerSendPackets(packetHolder, conn) {
|
|
28
|
-
this.conn = conn;
|
|
29
|
-
packetHolder.getTags().forEach(tag => {
|
|
30
|
-
const packet = packetHolder.getPacket(tag);
|
|
31
|
-
if (packet.dataBatching == 0)
|
|
32
|
-
return;
|
|
33
|
-
const code = packetHolder.getKey(tag);
|
|
34
|
-
this.initiateBatch(code, packet.dataBatching, packet.gzipCompression);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
initiateBatch(code, time, compressed) {
|
|
38
|
-
this.batchedData[code] = [];
|
|
39
|
-
this.batchInfo[code] = [time, compressed];
|
|
40
|
-
}
|
|
41
|
-
startBatch(code) {
|
|
42
|
-
const [time, compressed] = this.batchInfo[code];
|
|
43
|
-
this.batchTimeouts[code] = this.conn.setInterval(async () => {
|
|
44
|
-
if (this.batchedData[code].length == 0)
|
|
45
|
-
return;
|
|
46
|
-
const data = new Uint8Array(this.batchedData[code]);
|
|
47
|
-
this.conn.raw_send((0, BufferUtil_1.toPacketBuffer)(code, compressed ? await (0, CompressionUtil_1.compressGzip)(data) : data));
|
|
48
|
-
this.batchedData[code] = [];
|
|
49
|
-
delete this.batchTimeouts[code];
|
|
50
|
-
}, time);
|
|
51
|
-
}
|
|
52
|
-
batchPacket(code, data) {
|
|
53
|
-
const batch = this.batchedData[code];
|
|
54
|
-
batch.push(...(0, CompressionUtil_1.convertVarInt)(data.length));
|
|
55
|
-
data.forEach(val => batch.push(val));
|
|
56
|
-
if (!this.batchTimeouts[code])
|
|
57
|
-
this.startBatch(code);
|
|
58
|
-
}
|
|
59
|
-
static async unravelBatch(packet, _data, socket) {
|
|
60
|
-
const data = packet.gzipCompression ? await (0, CompressionUtil_1.decompressGzip)(_data) : _data;
|
|
61
|
-
const result = [];
|
|
62
|
-
for (let i = 0; i < data.length;) {
|
|
63
|
-
// must be >0 for it to apply
|
|
64
|
-
if (packet.maxBatchSize > 0 && result.length > packet.maxBatchSize)
|
|
65
|
-
return "Too big of batch";
|
|
66
|
-
// read batch length
|
|
67
|
-
const [off, varint] = (0, CompressionUtil_1.readVarInt)(data, i);
|
|
68
|
-
i = off;
|
|
69
|
-
// if it goes oob it's invalid
|
|
70
|
-
if (i + varint > data.length)
|
|
71
|
-
return "Tampered batch length";
|
|
72
|
-
// read sector
|
|
73
|
-
const sect = data.slice(i, i += varint);
|
|
74
|
-
// call the packets listeners
|
|
75
|
-
const listen = await packet.listen(sect, socket);
|
|
76
|
-
// if invalid, return that
|
|
77
|
-
if (typeof listen == 'string')
|
|
78
|
-
return "Batched packet: " + listen;
|
|
79
|
-
// store result
|
|
80
|
-
result.push([listen[0], !packet.dontSpread]);
|
|
81
|
-
}
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
exports.BatchHelper = BatchHelper;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export declare const MAX_BYTE = 255;
|
|
2
|
-
export declare const NEGATIVE_BYTE = 127;
|
|
3
|
-
export declare const MAX_SHORT = 65535;
|
|
4
|
-
export declare const SHORT_CC_OVERFLOW: number;
|
|
5
|
-
export declare const UVARINT_OVERFLOW: number, VARINT_CHAIN_FLAG = 128, // flag for chaining
|
|
6
|
-
NEGATIVE_VARINT: number, // splitting usable range in half for signed
|
|
7
|
-
VARINT_OVERFLOW: number, // for varint to overflow with negative; is 64
|
|
8
|
-
MAX_VSECT_SIZE = 7, // max continues
|
|
9
|
-
MAX_UVARINT: number, // max value from this, subtract one for overflow
|
|
10
|
-
MAX_VARINT: number;
|
|
11
|
-
export declare const ONE_EIGHT: number, ONE_FOURTH: number;
|
|
12
|
-
export declare const EMPTY_UINT8: Uint8Array<ArrayBuffer>;
|
|
13
|
-
export type SHORT_BITS = [high: number, low: number];
|
|
14
|
-
export declare function fromShort(short: SHORT_BITS): number;
|
|
15
|
-
export declare function toShort(n: number): SHORT_BITS;
|
|
16
|
-
export declare function toByte(n: number): number;
|
|
17
|
-
export declare const compressBools: (array: boolean[]) => number;
|
|
18
|
-
export declare const decompressBools: (byte: number) => boolean[];
|
|
19
|
-
export declare function convertFloat(flt: number): number[];
|
|
20
|
-
export declare function deconvertFloat(bytes: number[]): number;
|
|
21
|
-
export declare function convertDouble(double: number): number[];
|
|
22
|
-
export declare function deconvertDouble(bytes: number[]): number;
|
|
23
|
-
export declare function mapZigZag(n: number): number;
|
|
24
|
-
export declare function demapZigZag(n: number): number;
|
|
25
|
-
export declare function demapShort_ZZ(short: SHORT_BITS): number;
|
|
26
|
-
export declare function mapShort_ZZ(short: number): SHORT_BITS;
|
|
27
|
-
export declare function convertVarInt(num: number): number[];
|
|
28
|
-
export declare function readVarInt(arr: number[] | Uint8Array, off: number): [number, number];
|
|
29
|
-
export declare function deconvertVarInts(arr: Uint8Array | number[]): number[];
|
|
30
|
-
export declare const bytesToBits: (bytes: ArrayLike<number>) => string;
|
|
31
|
-
export declare const bitsToBytes: (bits: string) => Uint8Array<ArrayBuffer>;
|
|
32
|
-
export declare function compressGzip(data: Uint8Array<ArrayBuffer>, ident?: string): Promise<Uint8Array>;
|
|
33
|
-
export declare function decompressGzip(data: Uint8Array): Promise<Uint8Array>;
|
|
34
|
-
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
35
|
-
export declare function hexToBytes(hex: string): Uint8Array<ArrayBuffer>;
|
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright 2026 Lily (liwybloc)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.bitsToBytes = exports.bytesToBits = exports.decompressBools = exports.compressBools = exports.EMPTY_UINT8 = exports.ONE_FOURTH = exports.ONE_EIGHT = exports.MAX_VARINT = exports.MAX_UVARINT = exports.MAX_VSECT_SIZE = exports.VARINT_OVERFLOW = exports.NEGATIVE_VARINT = exports.VARINT_CHAIN_FLAG = exports.UVARINT_OVERFLOW = exports.SHORT_CC_OVERFLOW = exports.MAX_SHORT = exports.NEGATIVE_BYTE = exports.MAX_BYTE = void 0;
|
|
19
|
-
exports.fromShort = fromShort;
|
|
20
|
-
exports.toShort = toShort;
|
|
21
|
-
exports.toByte = toByte;
|
|
22
|
-
exports.convertFloat = convertFloat;
|
|
23
|
-
exports.deconvertFloat = deconvertFloat;
|
|
24
|
-
exports.convertDouble = convertDouble;
|
|
25
|
-
exports.deconvertDouble = deconvertDouble;
|
|
26
|
-
exports.mapZigZag = mapZigZag;
|
|
27
|
-
exports.demapZigZag = demapZigZag;
|
|
28
|
-
exports.demapShort_ZZ = demapShort_ZZ;
|
|
29
|
-
exports.mapShort_ZZ = mapShort_ZZ;
|
|
30
|
-
exports.convertVarInt = convertVarInt;
|
|
31
|
-
exports.readVarInt = readVarInt;
|
|
32
|
-
exports.deconvertVarInts = deconvertVarInts;
|
|
33
|
-
exports.compressGzip = compressGzip;
|
|
34
|
-
exports.decompressGzip = decompressGzip;
|
|
35
|
-
exports.bytesToHex = bytesToHex;
|
|
36
|
-
exports.hexToBytes = hexToBytes;
|
|
37
|
-
const BufferUtil_1 = require("../BufferUtil");
|
|
38
|
-
// this shit is so complex so i commented it...
|
|
39
|
-
// the highest 8-bit
|
|
40
|
-
exports.MAX_BYTE = 0xFF;
|
|
41
|
-
// we split the usable range in half to separate positive and negative encodings
|
|
42
|
-
exports.NEGATIVE_BYTE = 0x7F;
|
|
43
|
-
// the highest 16-bit
|
|
44
|
-
exports.MAX_SHORT = 0xFFFF;
|
|
45
|
-
// overflow for shorts in construction
|
|
46
|
-
exports.SHORT_CC_OVERFLOW = exports.MAX_BYTE + 1;
|
|
47
|
-
// for varint to overflow; is 128
|
|
48
|
-
exports.UVARINT_OVERFLOW = exports.NEGATIVE_BYTE + 1, exports.VARINT_CHAIN_FLAG = 0x80, exports.NEGATIVE_VARINT = Math.floor(exports.NEGATIVE_BYTE / 2), exports.VARINT_OVERFLOW = exports.NEGATIVE_VARINT + 1, exports.MAX_VSECT_SIZE = 7, exports.MAX_UVARINT = (exports.UVARINT_OVERFLOW ** exports.MAX_VSECT_SIZE) - 1, exports.MAX_VARINT = Math.floor(exports.MAX_UVARINT / 2); // max for negatives
|
|
49
|
-
// constants
|
|
50
|
-
exports.ONE_EIGHT = 1 / 8, exports.ONE_FOURTH = 1 / 4;
|
|
51
|
-
exports.EMPTY_UINT8 = new Uint8Array([]);
|
|
52
|
-
const TWO_POWS = [];
|
|
53
|
-
const twoPow = (num) => TWO_POWS[num] ??= Math.pow(2, num);
|
|
54
|
-
// reconstruction
|
|
55
|
-
function fromShort(short) {
|
|
56
|
-
// convert to number
|
|
57
|
-
return short[0] * exports.SHORT_CC_OVERFLOW + short[1];
|
|
58
|
-
}
|
|
59
|
-
// checks, conversion
|
|
60
|
-
function toShort(n) {
|
|
61
|
-
// no nan/infinity
|
|
62
|
-
if (!isFinite(n))
|
|
63
|
-
throw new Error("Can only use real numbers in shorts: " + n);
|
|
64
|
-
// limit check
|
|
65
|
-
if (n > exports.MAX_SHORT || n < 0)
|
|
66
|
-
throw new Error(`Short Numbers must be within range 0 and ${exports.MAX_SHORT}`);
|
|
67
|
-
// how many times it passes SHORT_OVERFLOW and the remainder
|
|
68
|
-
return [Math.floor(n / exports.SHORT_CC_OVERFLOW), n % exports.SHORT_CC_OVERFLOW];
|
|
69
|
-
}
|
|
70
|
-
// checks
|
|
71
|
-
function toByte(n) {
|
|
72
|
-
// no nan/infinity
|
|
73
|
-
if (!isFinite(n))
|
|
74
|
-
throw new Error("Can only use real numbers in bytes: " + n);
|
|
75
|
-
;
|
|
76
|
-
// limit check
|
|
77
|
-
if (n > exports.MAX_BYTE || n < -exports.MAX_BYTE - 1)
|
|
78
|
-
throw new Error(`Byte Numbers must be within range -${exports.MAX_BYTE + 1} and ${exports.MAX_BYTE}: ${n}`);
|
|
79
|
-
return n;
|
|
80
|
-
}
|
|
81
|
-
// boolean stuff
|
|
82
|
-
const compressBools = (array) => array.reduce((byte, val, i) => byte | (val << (7 - i)), 0);
|
|
83
|
-
exports.compressBools = compressBools;
|
|
84
|
-
const decompressBools = (byte) => [...Array(8)].map((_, i) => (byte & (1 << (7 - i))) !== 0);
|
|
85
|
-
exports.decompressBools = decompressBools;
|
|
86
|
-
// IEEE-754 single-precision float codec
|
|
87
|
-
const MAN_BITS = 23;
|
|
88
|
-
function parseBin(str) {
|
|
89
|
-
return parseInt(str, 2);
|
|
90
|
-
}
|
|
91
|
-
function parseMan(bin, isNormal) {
|
|
92
|
-
const mantissaInt = parseBin(bin);
|
|
93
|
-
let fraction = 0;
|
|
94
|
-
for (let i = 0; i < MAN_BITS; i++) {
|
|
95
|
-
if (mantissaInt & (1 << (MAN_BITS - i - 1))) {
|
|
96
|
-
fraction += twoPow(-(i + 1));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return (isNormal ? 1 : 0) + fraction;
|
|
100
|
-
}
|
|
101
|
-
// constants for floating point numbers
|
|
102
|
-
const FLOAT_EXPSIZE = 8, FLOAT_FRACTSIZE = 23;
|
|
103
|
-
const DOUBLE_EXPSIZE = 11, DOUBLE_FRACTSIZE = 52;
|
|
104
|
-
const FLOAT_SPECIAL = 0xFF, DOUBLE_SPECIAL = 0x7FF;
|
|
105
|
-
// assembles floating point values into 4 bytes
|
|
106
|
-
function assembleFloatingPoint(expSize, fractSize, sign, exponent, mantissa) {
|
|
107
|
-
const bin = sign.toString(2) + exponent.toString(2).padStart(expSize, "0") + mantissa.toString(2).padStart(fractSize, "0");
|
|
108
|
-
return (0, BufferUtil_1.splitArray)(Array.from(bin), 8).map((x) => parseBin(x.join("")));
|
|
109
|
-
}
|
|
110
|
-
function assembleSingleFloat(sign, exponent, mantissa) {
|
|
111
|
-
return assembleFloatingPoint(FLOAT_EXPSIZE, FLOAT_FRACTSIZE, sign, exponent, mantissa);
|
|
112
|
-
}
|
|
113
|
-
function assembleDoubleFloat(sign, exponent, mantissa) {
|
|
114
|
-
return assembleFloatingPoint(DOUBLE_EXPSIZE, DOUBLE_FRACTSIZE, sign, exponent, mantissa);
|
|
115
|
-
}
|
|
116
|
-
// https://stackoverflow.com/questions/3096646/how-to-convert-a-floating-point-number-to-its-binary-representation-ieee-754-i
|
|
117
|
-
// edited for clarity
|
|
118
|
-
function convertFloat(flt) {
|
|
119
|
-
if (isNaN(flt)) // Special case: NaN
|
|
120
|
-
return assembleSingleFloat(0, FLOAT_SPECIAL, 1); // Mantissa is nonzero for NaN
|
|
121
|
-
const sign = (flt < 0) ? 1 : 0;
|
|
122
|
-
flt = Math.abs(flt);
|
|
123
|
-
if (flt == 0.0) // Special case: +-0
|
|
124
|
-
return assembleSingleFloat(sign, 0, 0);
|
|
125
|
-
const exponent = Math.floor(Math.log(flt) / Math.LN2);
|
|
126
|
-
if (exponent > 127 || exponent < -126) // Special case: +-Infinity (and huge numbers)
|
|
127
|
-
return assembleSingleFloat(sign, 0xFF, 0); // Mantissa is zero for +-Infinity
|
|
128
|
-
const mantissa = flt / twoPow(exponent);
|
|
129
|
-
const roundMan = Math.round((mantissa - 1) * twoPow(23));
|
|
130
|
-
return assembleSingleFloat(sign, exponent + 127, roundMan & 0x7FFFFF);
|
|
131
|
-
}
|
|
132
|
-
function deconvertFloat(bytes) {
|
|
133
|
-
const bin = bytes.map(x => x.toString(2).padStart(8, "0")).join("");
|
|
134
|
-
// bit 1 = sign
|
|
135
|
-
// bits 2-9 = exponent
|
|
136
|
-
// bits 10-32 = mantissa
|
|
137
|
-
const sign = parseBin(bin[0]);
|
|
138
|
-
const rawExp = parseBin(bin.slice(1, 9));
|
|
139
|
-
const exp = rawExp == 0 ? -126 : rawExp - 127;
|
|
140
|
-
const man = parseMan(bin.slice(9, 32), rawExp != 0); // whether to add the implicit 1
|
|
141
|
-
let result;
|
|
142
|
-
if (rawExp == FLOAT_SPECIAL) {
|
|
143
|
-
result = man == 0 ? Infinity : NaN;
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
result = man * twoPow(exp);
|
|
147
|
-
}
|
|
148
|
-
return sign == 1 ? -result : result;
|
|
149
|
-
}
|
|
150
|
-
// https://stackoverflow.com/questions/72659156/convert-double-to-integer-mantissa-and-exponents
|
|
151
|
-
// turned to javascript
|
|
152
|
-
function convertDouble(double) {
|
|
153
|
-
if (isNaN(double))
|
|
154
|
-
return assembleDoubleFloat(0, DOUBLE_SPECIAL, 1); // nonzero for nan. sign doesnt effect anything
|
|
155
|
-
const sign = double < 0 ? 1 : 0;
|
|
156
|
-
if (!isFinite(double))
|
|
157
|
-
return assembleDoubleFloat(sign, DOUBLE_SPECIAL, 0); // zero for infinity
|
|
158
|
-
double = Math.abs(double);
|
|
159
|
-
let exponent, significand;
|
|
160
|
-
if (double == 0) {
|
|
161
|
-
exponent = 0;
|
|
162
|
-
significand = 0;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
exponent = Math.floor(Math.log2(double)) - 51;
|
|
166
|
-
significand = Math.floor(double / twoPow(exponent));
|
|
167
|
-
}
|
|
168
|
-
return assembleDoubleFloat(sign, exponent + 1023, significand);
|
|
169
|
-
}
|
|
170
|
-
function deconvertDouble(bytes) {
|
|
171
|
-
const bin = bytes.map(x => x.toString(2).padStart(8, "0")).join("");
|
|
172
|
-
// bit 1 = sign
|
|
173
|
-
// bits 2-12 = exponent
|
|
174
|
-
// bits 13-64 = mantissa
|
|
175
|
-
const sign = parseBin(bin[0]);
|
|
176
|
-
const rawExp = parseBin(bin.slice(1, 12));
|
|
177
|
-
const exp = rawExp == 0 ? -1022 : rawExp - 1023;
|
|
178
|
-
const man = parseBin(bin.slice(12, 64));
|
|
179
|
-
let result;
|
|
180
|
-
if (rawExp == DOUBLE_SPECIAL) {
|
|
181
|
-
result = man == 0 ? Infinity : NaN;
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
result = man * twoPow(exp);
|
|
185
|
-
}
|
|
186
|
-
return sign == 1 ? -result : result;
|
|
187
|
-
}
|
|
188
|
-
// zig_zag
|
|
189
|
-
function mapZigZag(n) {
|
|
190
|
-
return ((n << 1) ^ (n >> 31));
|
|
191
|
-
}
|
|
192
|
-
function demapZigZag(n) {
|
|
193
|
-
return (n >>> 1) ^ -((n & 1));
|
|
194
|
-
}
|
|
195
|
-
function demapShort_ZZ(short) {
|
|
196
|
-
return demapZigZag(fromShort(short));
|
|
197
|
-
}
|
|
198
|
-
function mapShort_ZZ(short) {
|
|
199
|
-
return toShort(mapZigZag(short));
|
|
200
|
-
}
|
|
201
|
-
// yeah!
|
|
202
|
-
function convertVarInt(num) {
|
|
203
|
-
if (num > exports.MAX_UVARINT || num < 0)
|
|
204
|
-
throw new Error(`Variable Ints must be within range 0 and ${exports.MAX_VARINT}: ${num}`);
|
|
205
|
-
if (num === 0)
|
|
206
|
-
return [0];
|
|
207
|
-
const result = [];
|
|
208
|
-
while (num > 0) {
|
|
209
|
-
let byte = num & 0x7F; // take 7 bits
|
|
210
|
-
num >>>= 7;
|
|
211
|
-
if (num > 0)
|
|
212
|
-
byte |= exports.VARINT_CHAIN_FLAG;
|
|
213
|
-
result.push(byte);
|
|
214
|
-
}
|
|
215
|
-
return result;
|
|
216
|
-
}
|
|
217
|
-
function readVarInt(arr, off) {
|
|
218
|
-
let num = 0;
|
|
219
|
-
let shift = 0;
|
|
220
|
-
let byte;
|
|
221
|
-
do {
|
|
222
|
-
byte = arr[off++];
|
|
223
|
-
num += (byte & ~exports.VARINT_CHAIN_FLAG) << shift;
|
|
224
|
-
shift += 7;
|
|
225
|
-
} while ((byte & exports.VARINT_CHAIN_FLAG) !== 0);
|
|
226
|
-
return [off, num];
|
|
227
|
-
}
|
|
228
|
-
function deconvertVarInts(arr) {
|
|
229
|
-
let res = [];
|
|
230
|
-
let i = 0;
|
|
231
|
-
while (i < arr.length) {
|
|
232
|
-
const [off, varint] = readVarInt(arr, i);
|
|
233
|
-
res.push(varint);
|
|
234
|
-
i = off;
|
|
235
|
-
}
|
|
236
|
-
return res;
|
|
237
|
-
}
|
|
238
|
-
const bytesToBits = (bytes) => Array.from(bytes).map(b => b.toString(2).padStart(8, '0')).join('');
|
|
239
|
-
exports.bytesToBits = bytesToBits;
|
|
240
|
-
const bitsToBytes = (bits) => new Uint8Array(bits.match(/.{1,8}/g)?.map(b => parseInt(b.padEnd(8, '0'), 2)) ?? []);
|
|
241
|
-
exports.bitsToBytes = bitsToBytes;
|
|
242
|
-
const gzipError = "Your browser is too old to support compression. Please update!";
|
|
243
|
-
async function compressGzip(data, ident = "") {
|
|
244
|
-
if (typeof CompressionStream === "undefined") {
|
|
245
|
-
if (typeof window !== "undefined")
|
|
246
|
-
window.alert(gzipError);
|
|
247
|
-
throw new Error(gzipError);
|
|
248
|
-
}
|
|
249
|
-
const stream = new Blob([data]).stream().pipeThrough(new CompressionStream("deflate-raw"));
|
|
250
|
-
const buffer = await new Response(stream).arrayBuffer();
|
|
251
|
-
if (data.length <= buffer.byteLength && ident != "") {
|
|
252
|
-
console.warn("WARN: Packet '" + ident + "' is small, and compressing it makes the size bigger!");
|
|
253
|
-
}
|
|
254
|
-
return new Uint8Array(buffer);
|
|
255
|
-
}
|
|
256
|
-
async function decompressGzip(data) {
|
|
257
|
-
if (typeof DecompressionStream === "undefined") {
|
|
258
|
-
if (typeof window !== "undefined")
|
|
259
|
-
window.alert(gzipError);
|
|
260
|
-
throw new Error(gzipError);
|
|
261
|
-
}
|
|
262
|
-
const stream = new Blob([data]).stream().pipeThrough(new DecompressionStream("deflate-raw"));
|
|
263
|
-
const buffer = await new Response(stream).arrayBuffer();
|
|
264
|
-
return new Uint8Array(buffer);
|
|
265
|
-
}
|
|
266
|
-
function bytesToHex(bytes) {
|
|
267
|
-
return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
|
268
|
-
}
|
|
269
|
-
;
|
|
270
|
-
function hexToBytes(hex) {
|
|
271
|
-
const bytes = new Uint8Array(hex.length / 2);
|
|
272
|
-
for (let i = 0; i < hex.length; i += 2) {
|
|
273
|
-
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
274
|
-
}
|
|
275
|
-
return bytes;
|
|
276
|
-
}
|
|
277
|
-
;
|