pub trait Logger {
/// Log a message at the given verbosity level.
fn log(&self, verbosity: u8, message: &str);
}
struct StderrLogger;
impl Logger for StderrLogger {
fn log(&self, verbosity: u8, message: &str) {
eprintln!("verbosity={verbosity}: {message}");
}
}
/// Only log messages matching a filtering predicate.
struct Filter<L, P> {
inner: L,
predicate: P,
}
impl<L, P> Filter<L, P>
where
L: Logger,
P: Fn(u8, &str) -> bool,
{
fn new(inner: L, predicate: P) -> Self {
Self { inner, predicate }
}
}
impl<L, P> Logger for Filter<L, P>
where
L: Logger,
P: Fn(u8, &str) -> bool,
{
fn log(&self, verbosity: u8, message: &str) {
if (self.predicate)(verbosity, message) {
self.inner.log(verbosity, message);
}
}
}
fn main() {
let logger = Filter::new(StderrLogger, |_verbosity, msg| msg.contains("yikes"));
logger.log(5, "FYI");
logger.log(1, "yikes, something went wrong");
logger.log(2, "uhoh");
}