1use std::sync::atomic::{AtomicBool, Ordering};
2
3pub static DEBUG_ENABLED: AtomicBool = AtomicBool::new(false);
4
5pub fn enable_debug() {
6 DEBUG_ENABLED.store(true, Ordering::Relaxed);
7}
8
9pub fn is_debug_enabled() -> bool {
10 DEBUG_ENABLED.load(Ordering::Relaxed)
11}
12
13#[cfg(feature = "debug")]
14pub fn log_hex(data: &[u8], stride: usize, mark: Option<&str>) {
15 if !is_debug_enabled() {
16 return;
17 }
18
19 const HEX_WIDTH: usize = 16;
20 let mut i = 0;
21
22 while i < data.len() {
23 if i % HEX_WIDTH == 0 {
24 if let Some(m) = mark {
25 print!("\n[{}] ", m);
26 }
27 print!("0x{:03x}:", i);
28 }
29
30 print!(" ");
31 for q in (0..stride).rev() {
32 if i + q < data.len() {
33 print!("{:02x}", data[i + stride - q - 1]);
34 }
35 }
36
37 i += stride;
38
39 if i % HEX_WIDTH == 0 && i <= data.len() {
40 print!(" ");
41 for j in (i.saturating_sub(HEX_WIDTH))..i.min(data.len()) {
42 let c = data[j];
43 let ch = if c >= 0x20 && c < 0x80 { c as char } else { '.' };
44 print!("{}", ch);
45 }
46 println!();
47 }
48 }
49
50 if i % HEX_WIDTH != 0 {
51 let remaining = HEX_WIDTH - (i % HEX_WIDTH);
52 for _ in 0..remaining {
53 print!(" ");
54 }
55 print!(" ");
56 for j in (i / HEX_WIDTH * HEX_WIDTH)..(i.min(data.len())) {
57 let c = data[j];
58 let ch = if c >= 0x20 && c < 0x80 { c as char } else { '.' };
59 print!("{}", ch);
60 }
61 println!();
62 }
63}
64
65#[cfg(not(feature = "debug"))]
66pub fn log_hex(_data: &[u8], _stride: usize, _mark: Option<&str>) {}