Skip to main content

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}