flashkraft_core/utils/logger.rs
1//! Debug Logging Utilities
2//!
3//! Centralized logging macros and utilities for FlashKraft.
4//! All debug logging is conditionally compiled and only active in debug builds.
5
6/// Debug logging macro for general application messages
7///
8/// Only prints in debug builds. Automatically prefixes with `\[DEBUG\]`.
9///
10/// # Example
11/// ```no_run
12/// # use flashkraft_core::debug_log;
13/// let path = "/path/to/image.iso";
14/// debug_log!("User selected image: {}", path);
15/// ```
16#[macro_export]
17macro_rules! debug_log {
18 ($($arg:tt)*) => {
19 #[cfg(debug_assertions)]
20 eprintln!("[DEBUG] {}", format!($($arg)*));
21 };
22}
23
24/// Debug logging macro for flash subscription messages
25///
26/// Only prints in debug builds. Automatically prefixes with `\[FLASH_DEBUG\]`.
27///
28/// # Example
29/// ```no_run
30/// # use flashkraft_core::flash_debug;
31/// let progress = 0.75;
32/// flash_debug!("Progress: {:.1}%", progress * 100.0);
33/// ```
34#[macro_export]
35macro_rules! flash_debug {
36 ($($arg:tt)*) => {
37 #[cfg(debug_assertions)]
38 eprintln!("[FLASH_DEBUG] {}", format!($($arg)*));
39 };
40}
41
42/// Debug logging macro for status messages
43///
44/// Only prints in debug builds. Automatically prefixes with `\[STATUS\]`.
45///
46/// # Example
47/// ```no_run
48/// # use flashkraft_core::status_log;
49/// status_log!("Starting flash operation");
50/// ```
51#[macro_export]
52macro_rules! status_log {
53 ($($arg:tt)*) => {
54 #[cfg(debug_assertions)]
55 eprintln!("[STATUS] {}", format!($($arg)*));
56 };
57}
58
59/// Conditional debug logging - only logs if condition is true
60///
61/// # Example
62/// ```no_run
63/// # use flashkraft_core::debug_if;
64/// let verbose_mode = true;
65/// let data = vec![1, 2, 3];
66/// debug_if!(verbose_mode, "Detailed info: {:?}", data);
67/// ```
68#[macro_export]
69macro_rules! debug_if {
70 ($condition:expr, $($arg:tt)*) => {
71 #[cfg(debug_assertions)]
72 if $condition {
73 eprintln!("[DEBUG] {}", format!($($arg)*));
74 }
75 };
76}
77
78/// Format a byte count as a compact human-readable string.
79///
80/// Uses binary prefixes (1 KiB = 1024 bytes) and one decimal place.
81/// Output examples: `"1.5G"`, `"512.0M"`, `"3.2K"`, `"42B"`.
82///
83/// # Example
84/// ```
85/// use flashkraft_core::fmt_bytes;
86/// assert_eq!(fmt_bytes(0), "0B");
87/// assert_eq!(fmt_bytes(1_023), "1023B");
88/// assert_eq!(fmt_bytes(1_024), "1.0K");
89/// assert_eq!(fmt_bytes(1_048_576), "1.0M");
90/// assert_eq!(fmt_bytes(1_073_741_824), "1.0G");
91/// ```
92pub fn fmt_bytes(bytes: u64) -> String {
93 const GIB: u64 = 1_073_741_824;
94 const MIB: u64 = 1_048_576;
95 const KIB: u64 = 1_024;
96
97 if bytes >= GIB {
98 format!("{:.1}G", bytes as f64 / GIB as f64)
99 } else if bytes >= MIB {
100 format!("{:.1}M", bytes as f64 / MIB as f64)
101 } else if bytes >= KIB {
102 format!("{:.1}K", bytes as f64 / KIB as f64)
103 } else {
104 format!("{bytes}B")
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 #[test]
111 fn test_debug_macros_compile() {
112 // These should compile without errors
113 debug_log!("Test message");
114 flash_debug!("Flash test: {}", 42);
115 status_log!("Status test");
116 debug_if!(true, "Conditional test");
117 }
118
119 // ── fmt_bytes ─────────────────────────────────────────────────────────────
120
121 #[test]
122 fn fmt_bytes_zero() {
123 assert_eq!(super::fmt_bytes(0), "0B");
124 }
125
126 #[test]
127 fn fmt_bytes_bytes_range() {
128 assert_eq!(super::fmt_bytes(1), "1B");
129 assert_eq!(super::fmt_bytes(1_023), "1023B");
130 }
131
132 #[test]
133 fn fmt_bytes_kib_boundary() {
134 assert_eq!(super::fmt_bytes(1_024), "1.0K");
135 assert_eq!(super::fmt_bytes(1_536), "1.5K");
136 assert_eq!(super::fmt_bytes(1_047_552), "1023.0K");
137 }
138
139 #[test]
140 fn fmt_bytes_mib_boundary() {
141 assert_eq!(super::fmt_bytes(1_048_576), "1.0M");
142 assert_eq!(super::fmt_bytes(524_288_000), "500.0M");
143 }
144
145 #[test]
146 fn fmt_bytes_gib_boundary() {
147 assert_eq!(super::fmt_bytes(1_073_741_824), "1.0G");
148 assert_eq!(super::fmt_bytes(32_212_254_720), "30.0G");
149 }
150}