feat: add new tests

This commit is contained in:
2026-08-07 15:29:02 +03:00
parent 8e6fbeabbf
commit 411b00c3ee
3 changed files with 125 additions and 13 deletions

View File

@@ -0,0 +1,79 @@
import 'dart:typed_data';
/// Класс для упаковки/распаковки текста в 6-битный формат.
/// 4 символа упаковываются ровно в 3 байта (сжатие ~62% для кириллицы).
abstract class CompactTextEncoder {
/// Словарь из 64 символов (индексы от 0 до 63)
static const String charset = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ -.,_';
/// Упаковывает строку [text] в байтовый массив Uint8List.
static Uint8List encode(String text) {
if (text.isEmpty) {
return Uint8List(0);
}
final String upperText = text.toUpperCase();
final List<int> indices = [];
// Преобразуем каждый символ в индекс от 0 до 63
for (int i = 0; i < upperText.length; i++) {
int idx = charset.indexOf(upperText[i]);
// Если символа нет в словаре, заменяем на пробел
if (idx == -1) {
idx = charset.indexOf(' ');
}
indices.add(idx);
}
// Добиваем длину до кратности 4 символам (символом '_')
while (indices.length % 4 != 0) {
indices.add(charset.indexOf('_'));
}
final int byteLength = (indices.length ~/ 4) * 3;
final Uint8List result = Uint8List(byteLength);
int byteIdx = 0;
for (int i = 0; i < indices.length; i += 4) {
int c1 = indices[i];
int c2 = indices[i + 1];
int c3 = indices[i + 2];
int c4 = indices[i + 3];
// Упаковка 4 x 6 бит (24 бита) в 3 байта по 8 бит
result[byteIdx++] = (c1 << 2) | (c2 >> 4);
result[byteIdx++] = ((c2 & 0x0F) << 4) | (c3 >> 2);
result[byteIdx++] = ((c3 & 0x03) << 6) | c4;
}
return result;
}
/// Распаковывает байтовый массив обратно в строку.
static String decode(Uint8List bytes) {
if (bytes.isEmpty) {
return '';
}
final StringBuffer sb = StringBuffer();
for (int i = 0; i < bytes.length; i += 3) {
int b1 = bytes[i];
int b2 = bytes[i + 1];
int b3 = bytes[i + 2];
int c1 = (b1 >> 2) & 0x3F;
int c2 = ((b1 & 0x03) << 4) | ((b2 >> 4) & 0x0F);
int c3 = ((b2 & 0x0F) << 2) | ((b3 >> 6) & 0x03);
int c4 = b3 & 0x3F;
sb.write(charset[c1]);
sb.write(charset[c2]);
sb.write(charset[c3]);
sb.write(charset[c4]);
}
// Удаляем заполнители и пробелы по краям
return sb.toString().replaceAll('_', '').trim();
}
}