testutils/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(__unstable_doc, feature(doc_auto_cfg, doc_notable_trait))]
3/*!
4## Features
5
6- **all**
7 All available features enabled
8
9- **std**
10 Enables standard library support. When enabled, the crate cannot be used in `no_std` environments.
11
12- **ext_traits**
13 Additional trait extensions:
14 - `BoolExt` - Adds `.ok_or_else()` method for `bool` type
15 - Re-exports `Pipe` and `Tap` traits from `tap` crate
16
17- **tiny_container**
18 Compact string (<=N: Inline(Stack), >N: Overflow to Heap):
19 - `TString<const N: usize>` type alias for `TinyString<[u8; N]>`
20 - `Formattable` trait
21 - Enables `format` support for `TString`
22 - `IntoBoxedStr` trait
23 - Adds `.into_boxed_str()` conversion
24
25- **os_cmd**
26 Configurable command builders:
27 - Preconfigured cargo command structs (e.g., `CargoDoc`, `CargoBuild`)
28 - Cross-platform command execution utilities
29*/
30extern crate alloc;
31
32#[cfg(feature = "os_cmd")]
33pub mod os_cmd;
34
35#[cfg(feature = "ext_traits")]
36/// Provides BoolExt(`.ok_or_else()`)
37pub mod traits;
38
39#[cfg(feature = "tiny_container")]
40/// TString & TinyVec
41pub mod tiny_container;
42
43/// Runs the given function and prints the elapsed time.
44/// It supports stable Rust.
45///
46/// ## Example
47///
48/// ```ignore
49/// fn bench_foo() {
50/// testutils::simple_benchmark(|| {
51/// foo() // Your code here...
52/// })
53/// }
54/// ```
55#[cfg(feature = "std")]
56pub fn simple_benchmark<U, F: FnOnce() -> U>(f: F) {
57 let start = std::time::Instant::now();
58 f();
59 eprintln!("Time taken: {:?}", start.elapsed());
60}
61
62/// `env!("CARGO_PKG_NAME")`
63#[macro_export]
64macro_rules! get_pkg_name {
65 () => {
66 env!("CARGO_PKG_NAME")
67 };
68}
69
70/// Similar to the `dbg!` macro, but inspects values by reference without moving
71/// them. This allows debugging values without transferring ownership, while
72/// showing the underlying value's type information (not reference types).
73///
74/// This macro uses [`log::debug!`] internally, so you must:
75/// 1. Configure a logger (e.g., `env_logger`) with debug level enabled
76/// 2. Initialize the logger before use
77///
78/// ## Key Differences from `dbg!`
79/// - Returns `()` instead of the original value
80/// - Requires explicit logger initialization
81///
82/// ## Examples
83///
84/// Basic usage with automatic type deduction
85///
86/// ```
87/// use testutils::dbg_ref;
88/// // Must initialize logger first:
89/// // env_logger::builder().filter_level(log::LevelFilter::Debug).init();
90///
91/// let counter = 42;
92/// dbg_ref!(counter); // [DEBUG] counter: i32 = 42
93///
94/// let message = "Hello";
95/// dbg_ref!(message); // [DEBUG] message: &str = "Hello"
96///
97/// let values = vec![(1, "a"), (2, "b")];
98/// dbg_ref!(values); // [DEBUG] values: alloc::vec::Vec<(i32, &str)> = [...]
99/// ```
100///
101/// Debugging multiple values
102///
103/// ```
104/// use testutils::dbg_ref;
105/// let width = 30;
106/// let label = "size";
107///
108/// dbg_ref!(width, label);
109/// // Outputs:
110/// // [DEBUG] width: i32 = 30
111/// // [DEBUG] label: &str = "size"
112/// ```
113///
114/// ## Implementation Notes
115/// 1. Uses `core::any::type_name_of_val` for type information
116/// 2. Formats output as: `{variable_name}: {type} = {debug_representation}`
117/// 3. Multiple arguments generate separate log entries
118#[macro_export]
119macro_rules! dbg_ref {
120 ($val:expr $(,)?) => {{
121 match &$val {
122 tmp => {
123 log::debug!(
124 "{name}: {type_name} = {tmp:?}",
125 name = stringify!($val),
126 type_name = core::any::type_name_of_val(&$val),
127 );
128 }
129 }
130 }};
131 ($($val:expr),+ $(,)?) => {
132 ($($crate::dbg_ref!($val)),+,)
133 };
134}
135
136/// Generates a list of tuples containing field names and their values
137///
138/// ## Example
139///
140/// ```
141/// use testutils::generate_struct_arr;
142///
143/// struct BuildStd {
144/// std: bool,
145/// core: bool,
146/// alloc: bool,
147/// }
148///
149/// let b = BuildStd {
150/// std: false,
151/// core: true,
152/// alloc: true,
153/// };
154///
155/// let arr = generate_struct_arr![ b => core, alloc, std ];
156/// assert_eq!(
157/// arr,
158/// [("core", true), ("alloc", true), ("std", false)]
159/// );
160/// ```
161#[macro_export]
162macro_rules! generate_struct_arr {
163 ($self:ident => $( $field:ident ),* $(,)? ) => {{
164 [
165 $( ( stringify!($field), $self.$field ), )*
166 ]
167 }};
168}