Треки
/
Rust
Rust
/
Вправи
/
Ксорцизм
Ксорцизм

Ксорцизм

Складна

Вказівки

Напишіть потоковий адаптер, який містить посилання на ключ і порозрядно виконує над ним XOR із довільними даними.

XOR - фундаментальна бінарна операція: для кожного біта вхідних даних встановлюємо відповідний біт вихідних даних у 1, якщо вхідні біти різняться. Якщо обидва вхідні біти дорівнюють 1 або обидва дорівнюють 0, то відповідний вихідний біт - 0.

Коли ми виконуємо XOR документа з ключем, ключ повторюється стільки разів, скільки потрібно, і утворюється вихідний документ, довжина якого дорівнює довжині вхідного.

Шифрування документа XOR-ом із ключем використовували в криптографії навіть на початку 1900-х років. Хоча як метод приховування даних XOR цілком застарів, він може стати напрочуд корисним для генерування шумних даних, які здаються випадковими, без потреби ускладнювати все справжньою випадковістю. Його досі подеколи використовують у сучасній криптографії для деяких шифрів: сам шифр - це лише механізм для генерування дуже випадкового, нескінченно довгого ключа, який потім застосовують до документа через XOR.

Одна цікава властивість XOR-шифрування - його симетричність: XOR будь-якого числа із самим собою дає 0, а XOR будь-якого числа з 0 повертає вхідне число без змін. Тож, щоб розшифрувати документ, зашифрований XOR-ом, потрібно знову зашифрувати його XOR-ом із тим самим ключем.

Без виділення памʼяті

Непрактично писати тест, який перевіряє, що наша структура містить посилання на ключ, а не копіює його. Так само непрактично доводити тестом, що ні munge, ні munge_in_place, ні будь-яка з їхніх допоміжних функцій не виділяють памʼять у купі. І все ж спробуйте написати своє рішення саме так.

Реалізація

Потрібно написати struct Xorcism, що містить посилання на ключ. Ця структура повинна надавати два методи: munge_in_place і munge. Перший змінює буфер байтів на місці. Другий - це адаптер ітератора: він приймає довільний ітератор даних і повертає новий ітератор даних.

Сигнатури заглушок у цій вправі здебільшого синтаксично правильні, але вони не компілюються: значною мірою сенс цієї вправи в тому, щоб ми навчилися користуватися часами життя та узагальненнями, тож заповнити їх доведеться самостійно. Ще одна мета цієї вправи - знайти доречне розбиття на частини, яке дасть змогу реалізувати обидва ці методи з мінімальним дублюванням роботи. Не бійтеся додавати допоміжні функції!

Корисні трейти

Ось трейти, які стануть у пригоді:

Бонусні тести

Ця вправа містить бонусні тести за прапорцем можливості io. Щоб увімкнути їх, виконайте

cargo test --features io

Для цих тестів потрібно реалізувати метод reader із такою сигнатурою

fn reader(self, impl Read) -> impl Read

і метод writer із такою сигнатурою

fn writer(self, impl Write) -> impl Write

Кожна з цих функцій перетворює структуру Xorcism на потоковий адаптер у відповідному напрямку. Вони використовують такі трейти:

Час життя поверненого значення munge

Через використання можливості impl Trait керування часом життя може бути трохи складним, коли ми реалізуємо метод munge. Може виявитися легше написати власний struct із реалізацією Iterator і повернути цей конкретний тип, принаймні для початку. Зрештою, варто спробувати реалізувати рішення безпосередньо за допомогою комбінаторів Iterator.


Джерело

Peter Goodspeed-Niklaus
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Rust Exercism

Час розпочати Ксорцизм?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Rust, а також 99 вправ та справжнє наставництво від людей, і все це безкоштовно.