1use arcref::ArcRef;
2use std::sync::Arc;
3
4#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
6pub enum Level {
7 INFO,
8 WARN,
9 ERROR,
10}
11
12pub trait Logger {
14 fn log(&self, level: Level, line: &str);
15}
16
17pub trait LoggerFactory {
18 fn new_logger(&self) -> ArcRef<dyn Logger>;
19}
20
21pub struct StdoutLogger;
23
24impl Logger for StdoutLogger {
25 fn log(&self, level: Level, line: &str) {
26 println!("{level:?}: {line}");
27 }
28}
29
30pub struct ConsoleFactory;
32
33impl LoggerFactory for ConsoleFactory {
34 fn new_logger(&self) -> ArcRef<dyn Logger> {
35 ArcRef::new_ref(&StdoutLogger)
37 }
38}
39
40pub struct FilteredLogger(Level, ArcRef<dyn Logger>);
42
43impl Logger for FilteredLogger {
44 fn log(&self, level: Level, line: &str) {
45 if level >= self.0 {
46 self.1.log(level, line);
47 }
48 }
49}
50
51pub struct FilteredLoggerFactory {
52 min_level: Level,
53 delegate: ArcRef<dyn Logger>,
54}
55
56impl LoggerFactory for FilteredLoggerFactory {
57 fn new_logger(&self) -> ArcRef<dyn Logger> {
58 ArcRef::new_arc(Arc::new(FilteredLogger(
59 self.min_level,
60 self.delegate.clone(),
61 )))
62 }
63}
64
65fn main() {
66 let console = ConsoleFactory.new_logger();
67 let filtered = FilteredLoggerFactory {
68 min_level: Level::WARN,
69 delegate: console,
70 };
71
72 let logger = filtered.new_logger();
73 logger.log(Level::INFO, "this will not print");
74 logger.log(Level::WARN, "but this will");
75 logger.log(Level::ERROR, "and so will this");
76}