Вправа: Трейт логгера

Давайте розробимо просту утиліту для ведення логів, використовуючи трейт Logger з методом log. Код, який може реєструвати свій прогрес, може отримати &impl Logger. Під час тестування це може призвести до запису повідомлень до тестового лог-файлу, тоді як у виробничій збірці повідомлення надсилатимуться до сервера логів.

Однак, наведений нижче StderrLogger реєструє всі повідомлення, незалежно від їхньої докладності. Ваше завдання - написати тип VerbosityFilter, який ігноруватиме повідомлення з максимальною докладностю.

Це поширений патерн: структура, що обгортає реалізацію трейту і реалізує той самий трейт, додаючи поведінку в процесі. Які ще типи обгорток можуть бути корисними у утиліті для ведення логів?

use std::fmt::Display;

pub trait Logger {
    /// Запишіть повідомлення із заданим рівнем докладності.
    fn log(&self, verbosity: u8, message: impl Display);
}

struct StderrLogger;

impl Logger for StderrLogger {
    fn log(&self, verbosity: u8, message: impl Display) {
        eprintln!("verbosity={verbosity}: {message}");
    }
}

fn do_things(logger: &impl Logger) {
    logger.log(5, "FYI");
    logger.log(2, "Uhoh");
}

// TODO: Визначте та реалізуйте `VerbosityFilter`.

fn main() {
    let l = VerbosityFilter { max_verbosity: 3, inner: StderrLogger };
    do_things(&l);
}