1extern crate libc;
2use std::{io::Write, mem::size_of, sync::atomic::AtomicI32};
3
4pub fn ref_to_bytes<T>(val: &T) -> &[u8] {
5 unsafe { std::slice::from_raw_parts(val as *const T as *const u8, size_of::<T>()) }
6}
7pub fn ref_to_bytes_mut<T>(val: &mut T) -> &mut [u8] {
8 unsafe { std::slice::from_raw_parts_mut(val as *mut T as *mut u8, size_of::<T>()) }
9}
10pub fn bytes_to_ref_mut<T>(buf: &mut [u8]) -> &mut T {
11 debug_assert!(
12 size_of::<T>() <= buf.len(),
13 "buf.len:{} < obj.size: {}",
14 buf.len(),
15 size_of::<T>()
16 );
17 unsafe {
18 let p = buf.as_mut_ptr() as *mut T;
19 &mut *p
20 }
21}
22pub fn bytes_to_ref<T>(buf: &[u8]) -> &T {
23 debug_assert!(
24 size_of::<T>() <= buf.len(),
25 "buf.len:{} < obj.size: {}",
26 buf.len(),
27 size_of::<T>()
28 );
29 unsafe {
30 let p = buf.as_ptr() as *const T;
31 &*p
32 }
33}
34
35pub fn localtime_r(seconds: i64, tm: &mut libc::tm) {
36 let t = seconds as libc::time_t;
37 unsafe {
38 #[cfg(target_os = "linux")]
39 {
40 libc::localtime_r(&t, tm);
41 }
42 #[cfg(not(target_os = "linux"))]
43 {
44 libc::localtime_s(tm, &t);
45 }
46 }
47}
48pub fn gmtime_r(seconds: i64, tm: &mut libc::tm) {
49 let t = seconds as libc::time_t;
50 unsafe {
51 #[cfg(target_os = "linux")]
52 {
53 libc::gmtime_r(&t, tm);
54 }
55 #[cfg(not(target_os = "linux"))]
56 {
57 libc::gmtime_s(tm, &t);
58 }
59 }
60}
61
62pub fn format_time(
63 buffer: &mut [u8],
64 nownanos: i64,
65 subsecond_digits: u32, gmt_time: bool,
67) -> &str {
68 debug_assert!(
69 subsecond_digits == 0
70 || subsecond_digits == 3
71 || subsecond_digits == 6
72 || subsecond_digits == 9
73 );
74 debug_assert!(buffer.len() as u32 > 17 + subsecond_digits + 1);
75 let (seconds, nanos) = (nownanos / 1000000000, nownanos % 1000000000);
76 let mut tm: libc::tm = unsafe { std::mem::MaybeUninit::zeroed().assume_init() };
77
78 if gmt_time {
79 gmtime_r(seconds, &mut tm);
80 } else {
81 localtime_r(seconds, &mut tm);
82 }
83 write!(
84 &mut buffer[..],
85 "{:04}{:02}{:02}-{:02}:{:02}:{:02}",
86 (tm.tm_year + 1900),
87 tm.tm_mon + 1,
88 tm.tm_mday,
89 tm.tm_hour + 1,
90 tm.tm_min,
91 tm.tm_sec
92 )
93 .unwrap();
94 let mut n = 17usize;
95 if subsecond_digits > 0 && subsecond_digits < 10 {
96 if subsecond_digits == 0 {
97 write!(&mut buffer[n..], ".{:03}", nanos / 1000000).unwrap();
98 } else if subsecond_digits == 3 {
99 write!(&mut buffer[n..], ".{:06}", nanos / 1000).unwrap();
100 } else {
101 write!(&mut buffer[n..], ".{:09}", nanos).unwrap();
102 }
103 n += ((subsecond_digits / 3) * 3 + 1) as usize;
104 }
105 std::str::from_utf8(&buffer[..n]).unwrap()
106}
107
108pub fn now_nanos() -> i64 {
109 std::time::SystemTime::now()
110 .duration_since(std::time::SystemTime::UNIX_EPOCH)
111 .unwrap()
112 .as_nanos() as i64
113}
114
115pub fn cpu_now_nanos() -> i64 {
117 let epoch: std::time::Instant = unsafe { std::mem::MaybeUninit::zeroed().assume_init() };
118 std::time::Instant::now().duration_since(epoch).as_nanos() as i64
119}
120
121pub struct Timer {
122 start: i64,
123 target: i64,
124}
125impl Timer {
126 pub fn new_millis(duration_millis: i64) -> Self {
127 let start = cpu_now_nanos();
128 Self {
129 start,
130 target: duration_millis * 1000000 + start,
131 }
132 }
133 pub fn expired(&self) -> bool {
134 cpu_now_nanos() >= self.target
135 }
136 pub fn elapsed_millis(&self) -> i64 {
137 (cpu_now_nanos() - self.start) / 1000000
138 }
139 pub fn sleep_or_expire(&self, duration_millis: i64) {
141 std::thread::sleep(std::time::Duration::from_millis(std::cmp::min(
142 duration_millis,
143 self.target - cpu_now_nanos(),
144 ) as u64));
145 }
146}
147
148pub const LOG_LEVEL_ERROR: i32 = 0;
149pub const LOG_LEVEL_INFO: i32 = 1;
150pub const LOG_LEVEL_TRACE: i32 = 2;
151pub const LOG_LEVEL_DEBUG: i32 = 3; #[cfg(debug_assertions)]
154static GLOBAL_LOG_LEVEL: AtomicI32 = AtomicI32::new(LOG_LEVEL_TRACE);
155
156#[cfg(not(debug_assertions))]
157static GLOBAL_LOG_LEVEL: AtomicI32 = AtomicI32::new(LOG_LEVEL_INFO);
158
159pub fn can_log(severity: i32) -> bool {
160 severity <= GLOBAL_LOG_LEVEL.load(std::sync::atomic::Ordering::Acquire)
161}
162pub fn set_log_level(severity: i32) {
163 GLOBAL_LOG_LEVEL.store(severity, std::sync::atomic::Ordering::Release);
164}
165#[macro_export]
167macro_rules! loginfo {
168 ($( $args:expr ),*) => {
169 if $crate::utils::can_log($crate::utils::LOG_LEVEL_INFO) {
170 let mut buf = [0u8; 40];
171 print!("[{}] [INFO] ", $crate::utils::format_time(&mut buf, $crate::utils::now_nanos(), 6, false));
172 println!( $( $args ),* );
173 }
175 }
176}
177
178#[macro_export]
179macro_rules! logerr {
180 ($( $args:expr ),*) => {
181 if $crate::utils::can_log($crate::utils::LOG_LEVEL_ERROR) {
182 let mut buf = [0u8; 40];
183 print!("[{}] [ERROR] ", $crate::utils::format_time(&mut buf, $crate::utils::now_nanos(), 6, false));
184 println!( $( $args ),* );
185 }
187 }
188}
189
190#[macro_export]
191macro_rules! logtrace {
192 ($( $args:expr ),*) => {
193 if $crate::utils::can_log($crate::utils::LOG_LEVEL_TRACE) {
194 let mut buf = [0u8; 40];
195 print!("[{}] [TRACE] ", $crate::utils::format_time(&mut buf, $crate::utils::now_nanos(), 6, false));
196 println!( $( $args ),* );
197 }
199 }
200}
201
202#[macro_export]
203#[cfg(debug_assertions)]
204macro_rules! dbglog {
206 ($( $args:expr ),*) => {
207 if $crate::utils::can_log($crate::utils::LOG_LEVEL_DEBUG) {
208 let mut buf = [0u8; 40];
209 print!("[{}] [DEBUG] ", $crate::utils::format_time(&mut buf, $crate::utils::now_nanos(), 6, false));
210 println!( $( $args ),* );
211 }
213 }
214}
215#[allow(unused_macros)]
216#[macro_export]
217#[cfg(not(debug_assertions))]
218macro_rules! dbglog {
219 ($( $args:expr ),*) => {
220 ()
221 };
222}
223
224#[cfg(test)]
225mod test {
226 use std::io::Write;
227
228 use crate::utils::{set_log_level, LOG_LEVEL_ERROR};
229
230 #[test]
233 pub fn test_vec_write() {
234 let mut v = Vec::<u8>::new();
235 set_log_level(LOG_LEVEL_ERROR);
237 v.resize(10, 1);
238 let mut s = &mut v[..];
239 s.write_fmt(format_args!("hello{}", 2))
240 .expect("failed to write to slice");
241 loginfo!("vec size: {}", v.len());
242 }
243 #[test]
244 pub fn test_log() {
245 let mut _buf = [0u8; 32];
246 dbglog!("test dbglog.");
247 loginfo!("any msg");
248 }
249}