use std::{
fmt::{
self,
Debug,
Display,
Formatter,
Write as _,
},
marker::PhantomData,
};
use crate::{
BoundedRedactedDisplay,
LogOutputLimit,
Redact,
RedactValue,
RedactionPolicy,
RedactionSession,
text::internal::LogEscapeWriter,
};
use super::{
bounded_redacted_display::format_bounded,
bounded_redacted_display::format_debug_bounded,
internal::mask_byte_limit,
};
#[must_use = "format the recursive keyed redaction view"]
pub struct RedactedKeyedMap<
'a,
M: ?Sized,
K: ?Sized = String,
V: ?Sized = String,
> {
map: &'a M,
policy: RedactionPolicy,
marker: PhantomData<fn() -> (*const K, *const V)>,
}
impl<'a, M: ?Sized, K: ?Sized, V: ?Sized> RedactedKeyedMap<'a, M, K, V> {
#[must_use = "format the recursive keyed redaction view"]
#[inline(always)]
pub const fn new(map: &'a M, policy: RedactionPolicy) -> Self {
Self {
map,
policy,
marker: PhantomData,
}
}
#[must_use = "format the bounded recursive keyed map display adapter"]
#[inline(always)]
pub const fn with_output_limit(
self,
limit: LogOutputLimit,
) -> BoundedRedactedDisplay<Self> {
BoundedRedactedDisplay::new(self, limit)
}
#[must_use = "format the bounded recursive keyed map display adapter"]
#[inline]
pub fn with_policy_output_limit(self) -> BoundedRedactedDisplay<Self> {
let limit =
LogOutputLimit::from(self.policy.limits().diagnostic_event());
BoundedRedactedDisplay::new(self, limit)
}
}
impl<
M: ?Sized,
K: AsRef<str> + Debug + ?Sized,
V: Redact + RedactValue + ?Sized,
> Debug for RedactedKeyedMap<'_, M, K, V>
where
for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
{
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let session = RedactionSession::diagnostic(&self.policy);
let view = RedactedKeyedMapSession::new(self.map, &session);
if mask_byte_limit().is_some() {
return Debug::fmt(&view, formatter);
}
format_debug_bounded(
&view,
LogOutputLimit::from(self.policy.limits().diagnostic_event()),
formatter,
)
}
}
mod session_view {
use std::{
fmt::{
self,
Debug,
Formatter,
},
marker::PhantomData,
};
use crate::{
Redact,
RedactValue,
RedactedKeyedValueSession,
RedactionSession,
};
#[must_use = "format the nested keyed redaction view"]
pub struct RedactedKeyedMapSession<
'map,
'session,
'policy,
M: ?Sized,
K: ?Sized = String,
V: ?Sized = String,
> {
map: &'map M,
session: &'session RedactionSession<'policy>,
marker: PhantomData<fn() -> (*const K, *const V)>,
}
impl<'map, 'session, 'policy, M: ?Sized, K: ?Sized, V: ?Sized>
RedactedKeyedMapSession<'map, 'session, 'policy, M, K, V>
{
#[inline(always)]
pub fn new(
map: &'map M,
session: &'session RedactionSession<'policy>,
) -> Self {
Self {
map,
session,
marker: PhantomData,
}
}
}
impl<
M: ?Sized,
K: AsRef<str> + Debug + ?Sized,
V: Redact + RedactValue + ?Sized,
> Debug for RedactedKeyedMapSession<'_, '_, '_, M, K, V>
where
for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
{
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let mut output = formatter.debug_map();
for (key, value) in self.map {
output.entry(
&key,
&RedactedKeyedValueSession::new(
key.as_ref(),
value,
self.session,
),
);
}
output.finish()
}
}
}
pub use session_view::RedactedKeyedMapSession;
impl<
M: ?Sized,
K: AsRef<str> + Debug + ?Sized,
V: Redact + RedactValue + ?Sized,
> Display for RedactedKeyedMapSession<'_, '_, '_, M, K, V>
where
for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
{
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let mut writer = LogEscapeWriter::new(formatter);
write!(&mut writer, "{self:?}")
}
}
impl<
M: ?Sized,
K: AsRef<str> + Debug + ?Sized,
V: Redact + RedactValue + ?Sized,
> Display for RedactedKeyedMap<'_, M, K, V>
where
for<'entry> &'entry M: IntoIterator<Item = (&'entry K, &'entry V)>,
{
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let session = RedactionSession::diagnostic(&self.policy);
let view = RedactedKeyedMapSession::new(self.map, &session);
format_bounded(
&view,
LogOutputLimit::from(self.policy.limits().diagnostic_event()),
formatter,
)
}
}