1use std::{
2 fs::File,
3 io::Write,
4 sync::{Arc, Mutex},
5};
6
7use crate::{
8 common::Common,
9 events::Event,
10 prelude::{ERef, LRef},
11 types::ID,
12};
13
14use bytes_kman::TBytes;
15
16#[derive(Clone, Debug, bytes_kman::Bytes)]
17pub enum Log {
18 Info(String),
19 Warning(String),
20 Error(String),
21}
22
23pub trait TLogger {
24 fn info(&mut self, data: impl Into<String>);
25 fn warn(&mut self, data: impl Into<String>);
26 fn error(&mut self, data: impl Into<String>);
27
28 fn flush(&mut self);
29 fn set_instant(&mut self, instant: bool);
30}
31
32pub trait TGetLogger {
33 fn get_logger(&self, dst: Option<Arc<Mutex<File>>>) -> Logger;
34}
35
36#[derive(Clone)]
37pub enum Ref {
38 Element(ERef),
39 Location(LRef),
40}
41
42impl From<Ref> for ID {
43 fn from(value: Ref) -> Self {
44 match value {
45 Ref::Element(e) => ID::Element(e.read().unwrap().id.clone()),
46 Ref::Location(l) => ID::Location(l.read().unwrap().id.clone()),
47 }
48 }
49}
50
51pub struct Logger {
52 dst: Option<Arc<Mutex<File>>>,
53 logs: Vec<Log>,
54 _ref: Ref,
55 instant: bool,
56}
57
58unsafe impl Sync for Logger {}
59unsafe impl Send for Logger {}
60
61impl Logger {
62 pub fn for_location(dst: Option<Arc<Mutex<File>>>, _ref: LRef) -> Self {
63 Self {
64 dst,
65 _ref: Ref::Location(_ref),
66 instant: false,
67 logs: Vec::new(),
68 }
69 }
70
71 pub fn for_element(dst: Option<Arc<Mutex<File>>>, _ref: ERef) -> Self {
72 Self {
73 dst,
74 _ref: Ref::Element(_ref),
75 instant: false,
76 logs: Vec::new(),
77 }
78 }
79}
80
81impl TLogger for Logger {
82 fn info(&mut self, data: impl Into<String>) {
83 let data: String = data.into();
84
85 if let Some(dst) = &self.dst {
86 let _ = write!(dst.lock().unwrap(), "Info: {data}");
87 }
88
89 self.logs.push(Log::Info(data));
90
91 if self.instant {
92 self.flush()
93 }
94 }
95
96 fn warn(&mut self, data: impl Into<String>) {
97 let data: String = data.into();
98
99 if let Some(dst) = &self.dst {
100 let _ = write!(dst.lock().unwrap(), "Warning: {data}");
101 }
102
103 self.logs.push(Log::Warning(data));
104
105 if self.instant {
106 self.flush()
107 }
108 }
109
110 fn error(&mut self, data: impl Into<String>) {
111 let data: String = data.into();
112
113 if let Some(dst) = &self.dst {
114 let _ = write!(dst.lock().unwrap(), "Error: {data}");
115 }
116
117 self.logs.push(Log::Error(data));
118
119 if self.instant {
120 self.flush()
121 }
122 }
123
124 fn flush(&mut self) {
125 for log in self.logs.iter() {
126 let _ = self
127 ._ref
128 .emit(Event::Log(self._ref.clone().into(), log.clone()));
129 }
130 self.logs.clear();
131 }
132
133 fn set_instant(&mut self, instant: bool) {
134 self.instant = instant;
135 }
136}
137
138impl Drop for Logger {
139 fn drop(&mut self) {
140 self.flush();
141 }
142}