debug_ignore/lib.rs
1// Copyright (c) The debug-ignore Contributors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! This library contains `DebugIgnore`, a newtype wrapper that causes a field to be skipped while
5//! printing out `Debug` output.
6//!
7//! # Examples
8//!
9//! ```rust
10//! use debug_ignore::DebugIgnore;
11//!
12//! // Some structs have many fields with large `Debug` implementations.
13//! #[derive(Debug)]
14//! struct InnerStructWithLotsOfDebugInfo {
15//! field: &'static str,
16//! // ...
17//! }
18//!
19//! #[derive(Debug)]
20//! pub struct PublicStruct {
21//! inner: DebugIgnore<InnerStructWithLotsOfDebugInfo>,
22//! }
23//!
24//! impl PublicStruct {
25//! pub fn new() -> Self {
26//! Self {
27//! // DebugIgnore<T> has a `From<T>` impl for the inner type; you can also construct
28//! // one explicitly.
29//! inner: InnerStructWithLotsOfDebugInfo { field: "field", /* ... */ }.into(),
30//! }
31//! }
32//! }
33//!
34//! let x = PublicStruct::new();
35//! assert_eq!(format!("{:?}", x), "PublicStruct { inner: ... }");
36//!
37//! // Fields within inner can still be accessed through the Deref impl.
38//! assert_eq!(x.inner.field, "field");
39//! ```
40//!
41//! # Why?
42//!
43//! Some structs have many fields with large `Debug` implementations. It can be really annoying to
44//! go through a ton of usually irrelevant `Debug` output.
45//!
46//! `DebugIgnore` is a zero-cost, zero-compile-time way to achieve a `Debug` impl that skips over a
47//! field.
48//!
49//! # Optional features
50//!
51//! `serde`: `serde` support with `#[serde(transparent)]`.
52//!
53//! # Rust version support
54//!
55//! The MSRV is **Rust 1.34** though this crate likely builds with older versions. This crate is
56//! too trivial to require anything more recent.
57//!
58//! Optional features may require newer versions of Rust.
59//!
60//! # Alternatives
61//!
62//! * Implement `Debug` by hand.
63//! * [`derivative`](https://crates.io/crates/derivative) has greater control over the behavior of
64//! `Debug` impls, at the cost of a compile-time proc-macro dependency.
65
66#![no_std]
67
68use core::{
69 fmt,
70 ops::{Deref, DerefMut},
71 str::FromStr,
72};
73
74/// A newtype wrapper that causes the field within to be ignored while printing out `Debug` output.
75///
76/// For more, see the [crate documentation](self).
77#[derive(Copy, Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
78#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
79#[repr(transparent)]
80#[cfg_attr(feature = "serde", serde(transparent))]
81pub struct DebugIgnore<T: ?Sized>(pub T);
82
83/// The point of this struct.
84impl<T: ?Sized> fmt::Debug for DebugIgnore<T> {
85 #[inline]
86 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87 write!(f, "...")
88 }
89}
90
91// ---
92// Other trait impls
93// ---
94
95impl<T> From<T> for DebugIgnore<T> {
96 #[inline]
97 fn from(t: T) -> Self {
98 Self(t)
99 }
100}
101
102impl<T: ?Sized> Deref for DebugIgnore<T> {
103 type Target = T;
104
105 #[inline]
106 fn deref(&self) -> &Self::Target {
107 &self.0
108 }
109}
110
111impl<T: ?Sized> DerefMut for DebugIgnore<T> {
112 #[inline]
113 fn deref_mut(&mut self) -> &mut Self::Target {
114 &mut self.0
115 }
116}
117
118impl<T: FromStr> FromStr for DebugIgnore<T> {
119 type Err = T::Err;
120
121 #[inline]
122 fn from_str(s: &str) -> Result<Self, Self::Err> {
123 s.parse().map(DebugIgnore)
124 }
125}
126
127impl<T: ?Sized + fmt::Display> fmt::Display for DebugIgnore<T> {
128 #[inline]
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 self.0.fmt(f)
131 }
132}
133
134impl<T: ?Sized, Q: ?Sized> AsRef<Q> for DebugIgnore<T>
135where
136 T: AsRef<Q>,
137{
138 #[inline]
139 fn as_ref(&self) -> &Q {
140 self.0.as_ref()
141 }
142}