1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) The debug-ignore Contributors
// SPDX-License-Identifier: MIT OR Apache-2.0

//! This library contains `DebugIgnore`, a newtype wrapper that causes a field to be skipped while
//! printing out `Debug` output.
//!
//! # Examples
//!
//! ```rust
//! use debug_ignore::DebugIgnore;
//!
//! // Some structs have many fields with large `Debug` implementations.
//! #[derive(Debug)]
//! struct InnerStructWithLotsOfDebugInfo {
//!     field: &'static str,
//!     // ...
//! }
//!
//! #[derive(Debug)]
//! pub struct PublicStruct {
//!     inner: DebugIgnore<InnerStructWithLotsOfDebugInfo>,
//! }
//!
//! impl PublicStruct {
//!     pub fn new() -> Self {
//!         Self {
//!             // DebugIgnore<T> has a `From<T>` impl for the inner type; you can also construct
//!             // one explicitly.
//!             inner: InnerStructWithLotsOfDebugInfo { field: "field", /* ... */ }.into(),
//!         }
//!     }
//! }
//!
//! let x = PublicStruct::new();
//! assert_eq!(format!("{:?}", x), "PublicStruct { inner: ... }");
//!
//! // Fields within inner can still be accessed through the Deref impl.
//! assert_eq!(x.inner.field, "field");
//! ```
//!
//! # Why?
//!
//! Some structs have many fields with large `Debug` implementations. It can be really annoying to
//! go through a ton of usually irrelevant `Debug` output.
//!
//! `DebugIgnore` is a zero-cost, zero-compile-time way to achieve a `Debug` impl that skips over a
//! field.
//!
//! # Optional features
//!
//! `serde`: `serde` support with `#[serde(transparent)]`.
//!
//! # Rust version support
//!
//! The MSRV is **Rust 1.34** though this crate likely builds with older versions. This crate is
//! too trivial to require anything more recent.
//!
//! Optional features may require newer versions of Rust.
//!
//! # Alternatives
//!
//! * Implement `Debug` by hand.
//! * [`derivative`](https://crates.io/crates/derivative) has greater control over the behavior of
//!   `Debug` impls, at the cost of a compile-time proc-macro dependency.

#![no_std]

use core::{
    fmt,
    ops::{Deref, DerefMut},
    str::FromStr,
};

/// A newtype wrapper that causes the field within to be ignored while printing out `Debug` output.
///
/// For more, see the [crate documentation](self).
#[derive(Copy, Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct DebugIgnore<T: ?Sized>(pub T);

/// The point of this struct.
impl<T: ?Sized> fmt::Debug for DebugIgnore<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "...")
    }
}

// ---
// Other trait impls
// ---

impl<T> From<T> for DebugIgnore<T> {
    #[inline]
    fn from(t: T) -> Self {
        Self(t)
    }
}

impl<T: ?Sized> Deref for DebugIgnore<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T: ?Sized> DerefMut for DebugIgnore<T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T: FromStr> FromStr for DebugIgnore<T> {
    type Err = T::Err;

    #[inline]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        s.parse().map(DebugIgnore)
    }
}

impl<T: ?Sized + fmt::Display> fmt::Display for DebugIgnore<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: ?Sized, Q: ?Sized> AsRef<Q> for DebugIgnore<T>
where
    T: AsRef<Q>,
{
    #[inline]
    fn as_ref(&self) -> &Q {
        self.0.as_ref()
    }
}