kutil_cli/debug/utils/
map.rs

1use super::super::{context::*, debuggable::*, format::*};
2
3use std::io::*;
4
5/// Debug into map key.
6pub const DEBUG_INTO_MAP_KEY: &str = "?";
7
8/// Debug into map value.
9pub const DEBUG_INTO_MAP_VALUE: &str = ":";
10
11/// Debug into map entry.
12pub const DEBUG_INTO_MAP_ENTRY: &str = "⚬"; // U+26AC
13
14/// Debug map entry separator.
15pub const DEBUG_MAP_ENTRY_SEPARATOR: &str = " ⇨"; // U+21E8
16
17/// Write an [Iterator] of [Debuggable] as a map.
18///
19/// Supports [DebugFormat::Reduced] and [DebugFormat::Compact].
20pub fn write_debug_as_map<'own, KeyT, ValueT, IteratorT, WriteT>(
21    iterator: IteratorT,
22    override_format: Option<DebugFormat>,
23    writer: &mut WriteT,
24    context: &DebugContext,
25) -> Result<()>
26where
27    KeyT: Debuggable + 'own,
28    ValueT: Debuggable + 'own,
29    IteratorT: Iterator<Item = (&'own KeyT, &'own ValueT)>,
30    WriteT: Write,
31{
32    let mut iterator = iterator.peekable();
33
34    if iterator.peek().is_none() {
35        context.separate(writer)?;
36        return context.theme.write_delimiter(writer, "{}");
37    }
38
39    let format = match override_format {
40        Some(format) => format,
41        None => context.format.clone(),
42    };
43
44    match format {
45        DebugFormat::Compact => {
46            context.separate(writer)?;
47            context.theme.write_delimiter(writer, "{")?;
48
49            while let Some((key, value)) = iterator.next() {
50                key.write_debug_for(writer, context)?;
51                context.theme.write_delimiter(writer, ":")?;
52                value.write_debug_for(writer, context)?;
53                if iterator.peek().is_some() {
54                    context.theme.write_delimiter(writer, ",")?;
55                }
56            }
57
58            context.theme.write_delimiter(writer, "}")
59        }
60
61        DebugFormat::Reduced => {
62            let key_context = context.child().with_separator(true).with_format(DebugFormat::Compact);
63            let value_context = context.child().with_inline(true).with_separator(true).increase_indentation();
64
65            let mut first = true;
66            while let Some((key, value)) = iterator.next() {
67                context.separate_or_indent_into(writer, DEBUG_INTO_MAP_ENTRY, first)?;
68                key.write_debug_for(writer, &key_context)?;
69
70                context.theme.write_delimiter(writer, DEBUG_MAP_ENTRY_SEPARATOR)?;
71                value.write_debug_for(writer, &value_context)?;
72
73                first = false;
74            }
75
76            Ok(())
77        }
78
79        DebugFormat::Verbose => {
80            let child_context = context.child().with_separator(true).increase_indentation();
81
82            let mut first = true;
83            while let Some((key, value)) = iterator.next() {
84                context.separate_or_indent_into(writer, DEBUG_INTO_MAP_KEY, first)?;
85                key.write_debug_for(writer, &child_context)?;
86
87                context.indent_into(writer, DEBUG_INTO_MAP_VALUE)?;
88                value.write_debug_for(writer, &child_context)?;
89
90                first = false;
91            }
92
93            Ok(())
94        }
95    }
96}