utils_box/
debug.rs

1//! # Debug utilities
2//! A toolbox of small utilities to debug data collections like vectors, maps, sets.
3//! Useful for debug printing the contents of those collections in a meaningful way.
4
5use core::fmt::{Binary, Display};
6use std::{
7    collections::{HashMap, HashSet},
8    fmt::Debug,
9    hash::Hash,
10    io,
11    io::prelude::*,
12};
13
14use crate::{log_debug, log_info};
15
16pub enum IdxMode {
17    Based0,
18    Based1,
19}
20
21pub fn vector_debug<T: Debug>(data: &[T], label: &str, idx_mode: IdxMode) {
22    let idx_mode: usize = match idx_mode {
23        IdxMode::Based0 => 0,
24        IdxMode::Based1 => 1,
25    };
26    let idx_padding = (data.len() as f32).log(10.0).floor() as usize + 1;
27    for (idx, value) in data.iter().enumerate() {
28        log_debug!("{}[{:idx_padding$}] = {:?}", label, idx + idx_mode, value);
29    }
30}
31
32pub fn vector_display<T: Display>(data: &[T], label: &str, idx_mode: IdxMode) {
33    let idx_mode: usize = match idx_mode {
34        IdxMode::Based0 => 0,
35        IdxMode::Based1 => 1,
36    };
37    let idx_padding = (data.len() as f32).log(10.0).floor() as usize + 1;
38    for (idx, value) in data.iter().enumerate() {
39        log_info!("{}[{:idx_padding$}] = {}", label, idx + idx_mode, value);
40    }
41}
42
43pub fn vector_display_bits<T: Binary>(data: &[T], label: &str, bits: usize, idx_mode: IdxMode) {
44    let idx_mode: usize = match idx_mode {
45        IdxMode::Based0 => 0,
46        IdxMode::Based1 => 1,
47    };
48    let idx_padding = (data.len() as f32).log(10.0).floor() as usize + 1;
49    for (idx, value) in data.iter().enumerate() {
50        log_info!(
51            "{}[{:idx_padding$}] = {:0bits$b}",
52            label,
53            idx + idx_mode,
54            value
55        );
56    }
57}
58
59pub fn hashmap_display<K: Display + Ord + Hash, V: Display>(data: &HashMap<K, V>, label: &str) {
60    let mut key_vec: Vec<&K> = data.keys().collect();
61    key_vec.sort_unstable();
62
63    for (idx, key) in key_vec.iter().enumerate() {
64        let value = data.get(key).unwrap();
65        log_info!("{}[{}]\t[{}] => {}", label, idx, key, value);
66    }
67}
68
69pub fn hashmap_debug<K: Debug + Ord + Hash, V: Debug>(data: &HashMap<K, V>, label: &str) {
70    let mut key_vec: Vec<&K> = data.keys().collect();
71    key_vec.sort_unstable();
72
73    for (idx, key) in key_vec.iter().enumerate() {
74        log_debug!("{}[{}]\t[{:?}]", label, idx, key);
75    }
76}
77
78pub fn hashset_display<K: Display + Ord + Hash, V: Display>(data: &HashSet<K>, label: &str) {
79    let mut key_vec: Vec<&K> = data.iter().collect();
80    key_vec.sort_unstable();
81
82    for (idx, key) in key_vec.iter().enumerate() {
83        log_info!("{}[{}]\t[{}]", label, idx, key);
84    }
85}
86
87pub fn hashset_debug<K: Debug + Ord + Hash, V: Debug>(data: &HashSet<K>, label: &str) {
88    let mut key_vec: Vec<&K> = data.iter().collect();
89    key_vec.sort_unstable();
90
91    for (idx, key) in key_vec.iter().enumerate() {
92        let value = data.get(key).unwrap();
93        log_debug!("{}[{}]\t[{:?}] => {:?}", label, idx, key, value);
94    }
95}
96
97/// Use this function to momentarily pause execution during debugging
98pub fn pause() {
99    let mut stdin = io::stdin();
100    let mut stdout = io::stdout();
101
102    // We want the cursor to stay at the end of the line, so we print without a newline and flush manually.
103    write!(stdout, "Press any key to continue...").unwrap();
104    stdout.flush().unwrap();
105
106    // Read a single byte and discard
107    let _ = stdin.read(&mut [0u8]).unwrap();
108}