1use std::{
11 fmt::{
12 self,
13 Debug,
14 Display,
15 Formatter,
16 Write as _,
17 },
18 marker::PhantomData,
19};
20
21use crate::{
22 BoundedRedactedDisplay,
23 LogOutputLimit,
24 Redact,
25 RedactValue,
26 RedactionPolicy,
27 RedactionSession,
28 text::internal::LogEscapeWriter,
29};
30
31use super::{
32 bounded_redacted_display::format_bounded,
33 bounded_redacted_display::format_debug_bounded,
34 internal::mask_byte_limit,
35};
36
37#[must_use = "format the recursive keyed redaction view"]
50pub struct RedactedKeyedMap<
51 'a,
52 M: ?Sized,
53 K: ?Sized = String,
54 V: ?Sized = String,
55> {
56 map: &'a M,
58 policy: RedactionPolicy,
60 marker: PhantomData<fn() -> (*const K, *const V)>,
62}
63
64impl<'a, M: ?Sized, K: ?Sized, V: ?Sized> RedactedKeyedMap<'a, M, K, V> {
65 #[must_use = "format the recursive keyed redaction view"]
76 #[inline(always)]
77 pub const fn new(map: &'a M, policy: RedactionPolicy) -> Self {
78 Self {
79 map,
80 policy,
81 marker: PhantomData,
82 }
83 }
84
85 #[must_use = "format the bounded recursive keyed map display adapter"]
95 #[inline(always)]
96 pub const fn with_output_limit(
97 self,
98 limit: LogOutputLimit,
99 ) -> BoundedRedactedDisplay<Self> {
100 BoundedRedactedDisplay::new(self, limit)
101 }
102
103 #[must_use = "format the bounded recursive keyed map display adapter"]
109 #[inline]
110 pub fn with_policy_output_limit(self) -> BoundedRedactedDisplay<Self> {
111 let limit =
112 LogOutputLimit::from(self.policy.limits().diagnostic_event());
113 BoundedRedactedDisplay::new(self, limit)
114 }
115}
116
117impl<
118 M: ?Sized,
119 K: AsRef<str> + Debug + ?Sized,
120 V: Redact + RedactValue + ?Sized,
121> Debug for RedactedKeyedMap<'_, M, K, V>
122where
123 for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
124{
125 #[inline]
140 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
141 let session = RedactionSession::diagnostic(&self.policy);
142 let view = RedactedKeyedMapSession::new(self.map, &session);
143 if mask_byte_limit().is_some() {
144 return Debug::fmt(&view, formatter);
145 }
146 format_debug_bounded(
147 &view,
148 LogOutputLimit::from(self.policy.limits().diagnostic_event()),
149 formatter,
150 )
151 }
152}
153
154mod session_view {
155 use std::{
156 fmt::{
157 self,
158 Debug,
159 Formatter,
160 },
161 marker::PhantomData,
162 };
163
164 use crate::{
165 Redact,
166 RedactValue,
167 RedactedKeyedValueSession,
168 RedactionSession,
169 };
170
171 #[must_use = "format the nested keyed redaction view"]
173 pub struct RedactedKeyedMapSession<
174 'map,
175 'session,
176 'policy,
177 M: ?Sized,
178 K: ?Sized = String,
179 V: ?Sized = String,
180 > {
181 map: &'map M,
182 session: &'session RedactionSession<'policy>,
183 marker: PhantomData<fn() -> (*const K, *const V)>,
184 }
185
186 impl<'map, 'session, 'policy, M: ?Sized, K: ?Sized, V: ?Sized>
187 RedactedKeyedMapSession<'map, 'session, 'policy, M, K, V>
188 {
189 #[inline(always)]
192 pub fn new(
193 map: &'map M,
194 session: &'session RedactionSession<'policy>,
195 ) -> Self {
196 Self {
197 map,
198 session,
199 marker: PhantomData,
200 }
201 }
202 }
203
204 impl<
205 M: ?Sized,
206 K: AsRef<str> + Debug + ?Sized,
207 V: Redact + RedactValue + ?Sized,
208 > Debug for RedactedKeyedMapSession<'_, '_, '_, M, K, V>
209 where
210 for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
211 {
212 #[inline]
214 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
215 let mut output = formatter.debug_map();
216 for (key, value) in self.map {
217 output.entry(
218 &key,
219 &RedactedKeyedValueSession::new(
220 key.as_ref(),
221 value,
222 self.session,
223 ),
224 );
225 }
226 output.finish()
227 }
228 }
229}
230
231pub use session_view::RedactedKeyedMapSession;
232
233impl<
234 M: ?Sized,
235 K: AsRef<str> + Debug + ?Sized,
236 V: Redact + RedactValue + ?Sized,
237> Display for RedactedKeyedMapSession<'_, '_, '_, M, K, V>
238where
239 for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
240{
241 #[inline]
243 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
244 let mut writer = LogEscapeWriter::new(formatter);
245 write!(&mut writer, "{self:?}")
246 }
247}
248
249impl<
250 M: ?Sized,
251 K: AsRef<str> + Debug + ?Sized,
252 V: Redact + RedactValue + ?Sized,
253> Display for RedactedKeyedMap<'_, M, K, V>
254where
255 for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
256{
257 #[inline]
273 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
274 let session = RedactionSession::diagnostic(&self.policy);
275 let view = RedactedKeyedMapSession::new(self.map, &session);
276 format_bounded(
277 &view,
278 LogOutputLimit::from(self.policy.limits().diagnostic_event()),
279 formatter,
280 )
281 }
282}