1use soulog::*;
2use crate::cli::VERBOSE;
3
4pub struct DynamicLogger {
5 verbose: Option<Verbose>,
6 quiet: Option<Quiet>,
7}
8
9macro_rules! one_or_other {
10 ($name:ident($one:expr, $two:expr) $code:block) => {'code: {
11 if let Some($name) = &mut $one {
12 break 'code ($code);
13 }
14 if let Some($name) = &mut $two {
15 break 'code ($code);
16 }
17
18 panic!("DynamicLogger of no logger type (should not happen)");
19 }}
20}
21
22impl Logger for DynamicLogger {
23 fn new() -> Self {
24 unsafe { if VERBOSE {
25 Self {
26 verbose: Some(Verbose::new()),
27 quiet: None,
28 }
29 } else {
30 Self {
31 verbose: None,
32 quiet: Some(Quiet::new()),
33 }
34 }}
35 }
36
37 fn hollow(&self) -> Self { Self::new() }
38
39 fn crash<T>(&mut self) -> T {one_or_other!(x(self.verbose, self.quiet) {
40 x.crash()
41 })}
42
43 fn verbose(&mut self, log: Log) {one_or_other!(x(self.verbose, self.quiet) {
44 x.verbose(log)
45 })}
46
47 fn vital(&mut self, log: Log) {one_or_other!(x(self.verbose, self.quiet) {
48 x.vital(log)
49 })}
50
51 fn error(&mut self, log: Log) -> ErrorResponse {one_or_other!(x(self.verbose, self.quiet) {
52 x.error(log)
53 })}
54}
55
56pub struct Verbose {
57 retry_count: u8,
58}
59
60impl Logger for Verbose {
61 fn new() -> Self { Self { retry_count: 2 } }
62 fn hollow(&self) -> Self { Self::new() }
63
64 fn crash<T>(&mut self) -> T {
65 let mut logger = Self::new();
66 log!((logger.vital) Diary("if the fatal error occurred during any writing to the archive, the archive may be corrupted! If so, then use `diary-cli rollback` to roll-back to the latest backup (that was made before any modification of the archive") as Warning);
67 std::process::exit(1)
68 }
69
70 fn verbose(&mut self, log: Log) {
71 self.retry_count = 2;
72 println!("{}", colour_format!(blue("["), cyan(log.origin), blue("] "), none(log.message)));
73 }
74
75 fn error(&mut self, log: Log) -> ErrorResponse {
76 let message = match log.log_type {
77 LogType::Failure => colour_format![blue("["), red(log.origin), blue("] "), red("Failure"), blue(": "), none(log.message)],
78 LogType::Fatal => colour_format![blue("["), red(log.origin), blue("] "), red("Fatal"), blue(": "), none(log.message)],
79 _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
80 }; println!("{message}");
81
82 if ErrorResponse::AskUser.allowed_in(&log) { return ErrorResponse::AskUser };
83 if ErrorResponse::Retry.allowed_in(&log) && self.retry_count > 0 {
84 self.retry_count -= 1;
85 std::thread::sleep(std::time::Duration::from_millis(800));
87 return ErrorResponse::Retry;
88 };
89
90 ErrorResponse::Crash
91 }
92
93 fn vital(&mut self, log: Log) {
94 let message = match log.log_type {
95 LogType::Inconvenience => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Inconvenience"), blue(": "), none(log.message)],
96 LogType::Warning => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Warning"), blue(": "), none(log.message)],
97 LogType::Result => colour_format![blue("["), green("Result"), blue("] "), green(log.origin), blue(": "), none(log.message)],
98 LogType::Log => colour_format!(blue("["), cyan(log.origin), blue("] "), none(log.message)),
99 _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
100 }; println!("{message}");
101 }
102}
103
104pub struct Quiet {
105 retry_count: u8,
106}
107
108impl Logger for Quiet {
109 fn new() -> Self { Self { retry_count: 2 } }
110 fn hollow(&self) -> Self { Self::new() }
111
112 fn crash<T>(&mut self) -> T {
113 let mut logger = Self::new();
114 log!((logger.vital) Diary("The archive may now be corrupted! Use `diary-cli rollback` to roll-back to the latest backup (that was made before any modification of the archive") as Warning);
115 std::process::exit(1)
116 }
117
118 fn verbose(&mut self, _: Log) {
119 self.retry_count = 2;
120 }
121
122 fn error(&mut self, log: Log) -> ErrorResponse {
123 let message = match log.log_type {
124 LogType::Failure => colour_format![blue("["), red(log.origin), blue("] "), red("Failure"), blue(": "), none(log.message)],
125 LogType::Fatal => colour_format![blue("["), red(log.origin), blue("] "), red("Fatal"), blue(": "), none(log.message)],
126 _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
127 }; println!("{message}");
128
129 if ErrorResponse::AskUser.allowed_in(&log) { return ErrorResponse::AskUser };
130 if ErrorResponse::Retry.allowed_in(&log) && self.retry_count > 0 {
131 self.retry_count -= 1;
132 std::thread::sleep(std::time::Duration::from_millis(800));
134 return ErrorResponse::Retry;
135 };
136
137 ErrorResponse::Crash
138 }
139
140 fn vital(&mut self, log: Log) {
141 let message = match log.log_type {
142 LogType::Inconvenience => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Inconvenience"), blue(": "), none(log.message)],
143 LogType::Warning => colour_format![blue("["), yellow(log.origin), blue("] "), yellow("Warning"), blue(": "), none(log.message)],
144 LogType::Result => colour_format![blue("["), green("Result"), blue("] "), green(log.origin), blue(": "), none(log.message)],
145 LogType::Log => colour_format!(blue("["), cyan(log.origin), blue("] "), none(log.message)),
146 _ => panic!("meta error: invalid error log type '{:?}'", log.log_type),
147 }; println!("{message}");
148 }
149}