subalfred_util/
lib.rs

1//! Collections of Subalfred utilities.
2
3#![deny(missing_docs, unused_crate_dependencies)]
4
5// std
6use std::time::Instant;
7
8/// Initialize an [`ExecutionTimer`] quickly.
9#[macro_export]
10macro_rules! execution_timer {
11	($meta:expr) => {
12		let _execution_timer = $crate::ExecutionTimer::init(|start| {
13			tracing::trace!("{} takes {} secs", $meta, start.elapsed().as_secs_f64())
14		});
15	};
16}
17
18/// A timer to measure the elapsed time of code block.
19///
20/// This struct holding a start time.
21/// While it get dropped, it will log the elapsed time.
22/// # Example
23/// ```
24/// use subalfred_util::ExecutionTimer;
25///
26/// // Must give a name to the timer, otherwise it will be dropped immediately.
27/// let _t = ExecutionTimer::init(|start| {
28/// 	tracing::trace!("`example` takes `{}` secs", start.elapsed().as_secs_f64())
29/// });
30/// ```
31#[allow(clippy::tabs_in_doc_comments)]
32pub struct ExecutionTimer<T>
33where
34	T: FnOnce(Instant),
35{
36	/// Start time.
37	pub start: Instant,
38	_tracing: Option<T>,
39}
40impl<T> ExecutionTimer<T>
41where
42	T: FnOnce(Instant),
43{
44	/// Initialize the timer.
45	pub fn init(tracing: T) -> Self {
46		Self { start: Instant::now(), _tracing: Some(tracing) }
47	}
48}
49impl<T> Drop for ExecutionTimer<T>
50where
51	T: FnOnce(Instant),
52{
53	fn drop(&mut self) {
54		let _ = self._tracing.take().map(|f| f(self.start));
55	}
56}
57
58#[test]
59#[tracing_test::traced_test]
60fn execution_timer_should_work() {
61	{
62		execution_timer!("test");
63	}
64
65	logs_assert(|log: &[&str]| {
66		let log = &log[0];
67
68		assert!(log.contains("test takes"));
69		assert!(log.contains("secs"));
70
71		Ok(())
72	});
73}