From 1a5c27bb0cac9819d3b7192612acefc406cb01b2 Mon Sep 17 00:00:00 2001 From: Verum Date: Thu, 5 Mar 2026 18:48:12 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=B5=D0=BA=D0=BE=D0=B4=D0=B5=D1=80=20ba?= =?UTF-8?q?se64?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/utils/encoding.py | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 backend/utils/encoding.py diff --git a/backend/utils/encoding.py b/backend/utils/encoding.py new file mode 100644 index 0000000..ef10989 --- /dev/null +++ b/backend/utils/encoding.py @@ -0,0 +1,48 @@ +from typing import Dict + +# Таблица Base64-подобного варианта +VariantBase64Table: str = ( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" +) +VariantBase64Dict: Dict[int, str] = { + i: VariantBase64Table[i] for i in range(len(VariantBase64Table)) +} +VariantBase64ReverseDict: Dict[str, int] = { + VariantBase64Table[i]: i for i in range(len(VariantBase64Table)) +} + + +def variant_base64_encode(bs: bytes) -> bytes: + """ + Пользовательский Base64 encode (малые блоки, little-endian). + + Аргументы: + - bs: bytes - исходные данные + + Возвращает: + - bytes: закодированные данные + """ + result: bytearray = bytearray() + blocks_count, left_bytes = divmod(len(bs), 3) + + # Полные блоки по 3 байта + for i in range(blocks_count): + b: bytes = bs[3*i:3*i+3] + coding_int: int = int.from_bytes(b, "little") + block: str = "".join( + VariantBase64Dict[(coding_int >> shift) & 0x3F] + for shift in (0, 6, 12, 18) + ) + result.extend(block.encode("ascii")) + + # Обработка оставшихся байт + if left_bytes: + b: bytes = bs[-left_bytes:] + coding_int: int = int.from_bytes(b, "little") + block: str = "".join( + VariantBase64Dict[(coding_int >> shift) & 0x3F] + for shift in range(0, left_bytes * 8 + 1, 6) + ) + result.extend(block.encode("ascii")) + + return bytes(result)