tuwunel_core/utils/
debug.rs1use std::fmt;
2
3pub struct TruncatedSlice<'a, T> {
8 inner: &'a [T],
9 max_len: usize,
10}
11
12pub struct TruncatedStr<'a> {
17 inner: &'a str,
18 max_len: usize,
19}
20
21pub fn slice_truncated<T: fmt::Debug>(
30 slice: &[T],
31 max_len: usize,
32) -> tracing::field::DebugValue<TruncatedSlice<'_, T>> {
33 tracing::field::debug(TruncatedSlice { inner: slice, max_len })
34}
35
36#[must_use]
45pub fn str_truncated(s: &str, max_len: usize) -> tracing::field::DebugValue<TruncatedStr<'_>> {
46 tracing::field::debug(TruncatedStr { inner: s, max_len })
47}
48
49#[macro_export]
50macro_rules! redacted_debug {
51 ($f:ident) => {
52 if $f.is_some() { "Some(<redacted>)" } else { "None" }
53 };
54}
55
56impl<T: fmt::Debug> fmt::Debug for TruncatedSlice<'_, T> {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 if self.inner.len() <= self.max_len {
59 write!(f, "{:?}", self.inner)
60 } else {
61 f.debug_list()
62 .entries(&self.inner[..self.max_len])
63 .entry(&"...")
64 .finish()
65 }
66 }
67}
68
69impl fmt::Debug for TruncatedStr<'_> {
70 #[expect(clippy::string_slice)]
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 if self.inner.len() <= self.max_len {
73 write!(f, "{:?}", self.inner)
74 } else {
75 let len = self
76 .inner
77 .char_indices()
78 .skip_while(|(i, _)| *i < self.max_len)
79 .map(|(i, _)| i)
80 .next()
81 .expect("At least one char_indice >= len for str");
82
83 write!(f, "{:?}...", &self.inner[..len])
84 }
85 }
86}