safelog: Add a MaybeRedacted wrapper too.

This is super helpful for cases where we want to write two nearly
identical implementations to format a type.
This commit is contained in:
Nick Mathewson 2022-11-21 14:07:49 -05:00
parent f91218c78d
commit f2c91ef56e
1 changed files with 38 additions and 0 deletions

View File

@ -217,6 +217,14 @@ pub trait Redactable: std::fmt::Display + std::fmt::Debug {
fn redacted(&self) -> Redacted<&Self> {
Redacted(self)
}
/// Return a smart pointer that redacts this object if `redact` is true.
fn maybe_redacted(&self, redact: bool) -> MaybeRedacted<&Self> {
if redact {
MaybeRedacted::Redacted(Redacted(self))
} else {
MaybeRedacted::NotRedacted(self)
}
}
}
impl<'a, T: Redactable + ?Sized> Redactable for &'a T {
@ -278,6 +286,36 @@ impl<T: Redactable> std::fmt::Debug for Redacted<T> {
}
}
/// An object that may or may not be redacted.
///
/// Used to implement conditional redaction
#[derive(Clone)]
#[allow(clippy::exhaustive_enums)]
pub enum MaybeRedacted<T: Redactable> {
/// A variant where we are redacting the object.
Redacted(Redacted<T>),
/// A variant where we are not redacting the object.
NotRedacted(T),
}
impl<T: Redactable> std::fmt::Display for MaybeRedacted<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MaybeRedacted::Redacted(v) => std::fmt::Display::fmt(v, f),
MaybeRedacted::NotRedacted(v) => std::fmt::Display::fmt(v, f),
}
}
}
impl<T: Redactable> std::fmt::Debug for MaybeRedacted<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MaybeRedacted::Redacted(v) => std::fmt::Debug::fmt(v, f),
MaybeRedacted::NotRedacted(v) => std::fmt::Debug::fmt(v, f),
}
}
}
#[cfg(test)]
mod test {
#![allow(clippy::unwrap_used)]