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); }