diff --git a/README.md b/README.md index 7639a01..203915f 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,58 @@ Исходный файл вопросов: `json.zip`, кодировка `UTF-8`. -Выходная база: файл `./db/data.mdb`, формат базы [LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database). - -Работа с базой выполняется с помощью [ledb](https://crates.io/crates/ledb). - При загрузке базы информация о пакете(файле/турнире) дублируется в каждом вопросе. +## Выходной формат данных + +Для хранения данных используется [bincode](https://crates.io/crates/bincode) и [zstd](https://crates.io/crates/zstd). +Данные вопросов в виде структуры сериализуются через `bincode` в бинарные данные и сжимаются `zstd`. Каждый вопрос сериализуется и сжимается отдельно. +В файле сжатые данные храняться последовательно, после заголовка файла. + +### Заголовок файла + +В заголовке хранятся только смещения каждого сжатого блока данных, и дополнительно, смещение указывающее на конец файла. +Смещение указывается в виде 32-битного беззнакового целового числа `u32`, сохраненного в виде 4-х байтов от младшего к старшему ([Little Endian](https://ru.wikipedia.org/wiki/Порядок_байтов#Порядок_от_младшего_к_старшему)). + +Пример заголовка: + +~~~ +00: 10 00 00 00 +04: 1A 00 00 00 +08: 2E 00 00 00 +0А: 3A 00 00 00 +~~~ + +данные: + +~~~ +10: 00 00 00 00 00 00 00 00 00 00 +1A: 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 +2E: 00 00 00 00 00 00 00 00 00 00 + 00 00 +3A: (EOF) +~~~ + +В этом примере сохранены 3 записи: + +1. смещение **0x10**, длина **10** байт +2. смещение **0x1A**, длина **20** байт +3. смещение **0x2E**, длина **12** байт + +Размер файла - 58 байт (0x3A), размер заголовка 16 байт (0x10). + +### Чтение данных + +Пусть размер записи заголовка в байтах = **`M`**, количество записей в файле = **`N`**. + +Тогда для того чтобы: + +- Найти **`N`**, нужно прочитать первую запись (**`M`** байт) в начале файла и разделить её значение на **`M`**; +- Найти элемент данных с индексом **`i`**, нужно последовательно прочитать 2 записи (**`M * 2`** байт), начиная c индекса **`i`** (по смещению в файле: **`i * M`**). Смещением будет значение по индексу **`i`**, длинной - разница между значениями по индексам **`i + 1`** и **`i`**. + +Далее для каждого вопроса отдельно предполагается распаковка данных через `zstd` и десериализация через `bincode`. + ## Ссылки - Источник вопросов: http://db.chgk.info