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