1use std::sync::{Mutex, Once};
2
3#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
4pub enum LogLevel {
5 V,
6 D,
7 I,
8 W,
9 E,
10 S,
11}
12
13impl LogLevel {
14 pub fn index(&self) -> u32 {
15 match self {
16 LogLevel::V => 0,
17 LogLevel::D => 1,
18 LogLevel::I => 2,
19 LogLevel::W => 3,
20 LogLevel::E => 4,
21 LogLevel::S => 5,
22 }
23 }
24
25 pub fn greater_than(&self, o: &Self) -> bool {
26 return self.index() > o.index();
27 }
28
29 pub fn greater_or_equal(&self, o: &Self) -> bool {
30 return self.index() >= o.index();
31 }
32
33 pub fn less_than(&self, o: &Self) -> bool {
34 return self.index() < o.index();
35 }
36
37 pub fn less_or_equal(&self, o: &Self) -> bool {
38 return self.index() <= o.index();
39 }
40}
41
42static INIT: Once = Once::new();
43static mut LOG_LEVEL: Option<Mutex<LogLevel>> = None;
44
45fn init() {
46 INIT.call_once(|| unsafe { LOG_LEVEL = Some(Mutex::new(LogLevel::I)) });
47}
48
49pub fn set_log_level(level: LogLevel) {
50 init();
51 unsafe {
52 if let Some(ref mutex) = LOG_LEVEL {
53 let mut ll = mutex.lock().unwrap();
54 *ll = level;
55 }
56 }
57}
58
59pub fn get_log_level() -> LogLevel {
60 init();
61
62 unsafe {
63 if let Some(ref mutex) = LOG_LEVEL {
64 let ll = mutex.lock().unwrap();
65 match *ll {
66 LogLevel::V => LogLevel::V,
67 LogLevel::D => LogLevel::D,
68 LogLevel::I => LogLevel::I,
69 LogLevel::W => LogLevel::W,
70 LogLevel::E => LogLevel::E,
71 LogLevel::S => LogLevel::S,
72 }
73 } else {
74 LogLevel::I
75 }
76 }
77}
78
79fn p(current_level: LogLevel, log_level: &LogLevel, msg: &str) {
80 if log_level.less_than(¤t_level) {
81 return;
82 }
83 println!("{msg}");
84}
85
86pub fn v(msg: &str) {
87 let current_level = get_log_level();
88 p(current_level, &LogLevel::V, msg)
89}
90
91pub fn d(msg: &str) {
92 let current_level = get_log_level();
93 p(current_level, &LogLevel::D, msg)
94}
95
96pub fn i(msg: &str) {
97 let current_level = get_log_level();
98 p(current_level, &LogLevel::I, msg)
99}
100
101pub fn w(msg: &str) {
102 let current_level = get_log_level();
103 p(current_level, &LogLevel::W, msg)
104}
105
106pub fn e(msg: &str) {
107 let current_level = get_log_level();
108 p(current_level, &LogLevel::E, msg)
109}
110
111#[cfg(test)]
112mod tests {
113 use crate::set_log_level;
114
115 use super::*;
116
117 #[test]
118 fn log() {
119 set_log_level(LogLevel::V);
120 println!("log_level:{:?}", get_log_level());
121 v("verbose");
122 d("debug");
123 i("info");
124 w("warn");
125 e("error");
126
127 set_log_level(LogLevel::D);
128 println!("log_level:{:?}", get_log_level());
129 v("verbose");
130 d("debug");
131 i("info");
132 w("warn");
133 e("error");
134
135 set_log_level(LogLevel::I);
136 println!("log_level:{:?}", get_log_level());
137 v("verbose");
138 d("debug");
139 i("info");
140 w("warn");
141 e("error");
142
143 set_log_level(LogLevel::W);
144 println!("log_level:{:?}", get_log_level());
145 v("verbose");
146 d("debug");
147 i("info");
148 w("warn");
149 e("error");
150
151 set_log_level(LogLevel::E);
152 println!("log_level:{:?}", get_log_level());
153 v("verbose");
154 d("debug");
155 i("info");
156 w("warn");
157 e("error");
158
159 set_log_level(LogLevel::S);
160 println!("log_level:{:?}", get_log_level());
161 v("verbose");
162 d("debug");
163 i("info");
164 w("warn");
165 e("error");
166 }
167}