use std::{
fmt::{
self,
Debug,
Display,
Formatter,
},
marker::PhantomData,
};
use crate::{
BoundedRedactedDisplay,
LogOutputLimit,
RedactMapValue,
RedactionPolicy,
RedactionSession,
};
use super::bounded_redacted_display::format_bounded;
use super::internal::mask_byte_limit;
#[must_use = "format or serialize the redacted map view"]
pub struct RedactedMap<'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> RedactedMap<'a, M, K, V> {
#[inline(always)]
pub const fn new(map: &'a M, policy: RedactionPolicy) -> Self {
Self {
map,
policy,
marker: PhantomData,
}
}
#[inline(always)]
pub const fn with_output_limit(
self,
limit: LogOutputLimit,
) -> BoundedRedactedDisplay<Self> {
BoundedRedactedDisplay::new(self, limit)
}
#[must_use = "format the bounded redacted 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: RedactMapValue<K, V> + ?Sized, K: ?Sized, V: ?Sized> Debug
for RedactedMap<'_, M, K, V>
{
#[inline(always)]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let session = RedactionSession::diagnostic(&self.policy);
let view = RedactedMapSession::new(self.map, &session);
if mask_byte_limit().is_some() {
return Debug::fmt(&view, formatter);
}
super::bounded_redacted_display::format_debug_bounded(
&view,
LogOutputLimit::from(self.policy.limits().diagnostic_event()),
formatter,
)
}
}
mod session_view {
use std::{
fmt::{
self,
Debug,
Display,
Formatter,
Write as _,
},
marker::PhantomData,
};
use crate::{
RedactMapValue,
RedactionSession,
text::internal::LogEscapeWriter,
};
#[must_use = "format the nested redacted map view"]
pub struct RedactedMapSession<
'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>
RedactedMapSession<'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: RedactMapValue<K, V> + ?Sized, K: ?Sized, V: ?Sized> Debug
for RedactedMapSession<'_, '_, '_, M, K, V>
{
#[inline(always)]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
self.map.fmt_redacted_map(self.session, formatter)
}
}
impl<M: RedactMapValue<K, V> + ?Sized, K: ?Sized, V: ?Sized> Display
for RedactedMapSession<'_, '_, '_, M, K, V>
{
#[inline(always)]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let mut writer = LogEscapeWriter::new(formatter);
write!(&mut writer, "{self:?}")
}
}
}
pub use session_view::RedactedMapSession;
impl<M: RedactMapValue<K, V> + ?Sized, K: ?Sized, V: ?Sized> Display
for RedactedMap<'_, M, K, V>
{
#[inline]
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
let session = RedactionSession::diagnostic(&self.policy);
let view = RedactedMapSession::new(self.map, &session);
format_bounded(
&view,
LogOutputLimit::from(self.policy.limits().diagnostic_event()),
formatter,
)
}
}
#[cfg(feature = "serde")]
impl<M: crate::domain::RedactMapSerialize<K, V> + ?Sized, K: ?Sized, V: ?Sized>
serde::Serialize for RedactedMap<'_, M, K, V>
{
#[inline(always)]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.map.serialize_redacted_map(&self.policy, serializer)
}
}