Exercício: Trait de Logger

Vamos projetar um utilitário de registro (log) simples, usando um trait Logger com um método log. O código que pode registrar seu progresso pode então receber um &impl Logger. Nos testes, isso pode colocar mensagens no arquivo de log de teste, enquanto em uma compilação de produção, ele enviaria mensagens para um servidor de log.

No entanto, o StderrLogger fornecido abaixo registra todas as mensagens, independentemente da verbosidade. Sua tarefa é escrever um tipo VerbosityFilter que ignorará mensagens acima de uma verbosidade máxima.

Este é um padrão comum: uma struct que envolve uma implementação de trait e implementa esse mesmo trait, adicionando comportamento no processo. Que outros tipos de wrappers podem ser úteis em um utilitário de registro?

use std::fmt::Display; pub trait Logger { /// Registra uma mensagem no nível de verbosidade fornecido. fn log(&self, verbosity: u8, message: impl Display); } struct StderrLogger; impl Logger for StderrLogger { fn log(&self, verbosity: u8, message: impl Display) { eprintln!("verbosidade={verbosity}: {message}"); } } fn do_things(logger: &impl Logger) { logger.log(5, "PSC (_FYI_)"); logger.log(2, "oh-oh"); } // TODO: Definir e implementar `VerbosityFilter`. fn main() { let l = VerbosityFilter { max_verbosity: 3, inner: StderrLogger }; do_things(&l); }