· 2 мин чтения
QR-код с нуля: Рид-Соломон, маски и как доказать верность
Как устроен QR-кодер на TypeScript без зависимостей и четыре независимых способа проверить, что матрица правильная.
qr-svg написан без единой runtime-зависимости: весь ISO/IEC 18004 для версий 1–40 лежит в src/qr/. Самое интересное здесь не генерация, а доказательство.
Из чего состоит кодер
- Поле GF(256) и арифметика в нём.
- Кодирование Рида-Соломона: байты коррекции как остаток от деления многочлена.
- Чередование блоков для версий с несколькими блоками.
- Шаблоны (поисковые, выравнивающие, синхронизация), форматная и версионная информация.
- Восемь масок и штрафы для выбора лучшей.
Как проверена верность
- Эталоны стандарта. Пример ISO «01234567» в 1-M и разбор «HELLO WORLD» в 1-Q совпадают по байтам коррекции.
- Независимая реализация. Матрицы сверяются бит в бит с
qrcode-generator(devDependency): 12 текстов × 4 уровня и 80 случайных строк. - Сторонний декодер. jsQR читает все 160 сочетаний «версия × уровень», кроме 23-L, которую не читает и эталон (матрицы идентичны, тест это фиксирует).
- Свой декодер с проверкой нулевых синдромов Рида-Соломона, независимой от деления в кодировщике.
Маски
Автовыбор маски у нас и у эталона часто различается: штрафы считаются чуть по-разному, обе маски корректны. Поэтому теста «выбрали ту же маску» намеренно нет. Сверка идёт с маской, взятой из форматной информации эталона.
Оговорка
Готовой матрицы из самого стандарта в репозитории нет: её роль играет сверка с независимой реализацией. Нет Kanji, ECI, смешанных сегментов и Micro QR. Тестов 45; на нагрузке с четвертью тяжёлых запросов (версия 37) p50 131 мс, p95 272 мс.