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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
use ;
use Zeroize;
/// Opaque `Debug` for secret-bearing types.
///
/// This module provides the [`OpaqueDebug`] marker trait and a `#[derive(OpaqueDebug)]`
/// macro that **also** implements [`core::fmt::Debug`] for your type in a way that
/// **never** reveals internal data.
///
/// By default, the generated `Debug` implementation prints a placeholder that includes
/// the type's fully-qualified name via [`core::any::type_name`]:
///
/// You can override this placeholder with an attribute on the type.
///
/// ## Why use this?
///
/// - Prevents accidental leakage of secrets (keys, tokens, passwords) via `Debug`
/// in logs or error messages.
/// - Keeps a meaningful breadcrumb (the type name) for diagnostics without exposing data.
/// - Allows the usage of [`Debug`] on outer types without risk.
///
/// ## What it generates
///
/// `#[derive(OpaqueDebug)]` generates:
///
/// 1. An impl of the marker trait:
/// ```ignore
/// impl OpaqueDebug for YourType {}
/// ```
/// 2. An impl of `core::fmt::Debug` that **never** formats internal fields.
///
/// ## Usage
///
/// ### Basic: default placeholder uses the fully-qualified type name
///
/// ```rust
/// # mod vitaminc { pub mod protected { pub use vitaminc_protected::*; } }
/// use vitaminc::protected::OpaqueDebug;
///
/// #[derive(OpaqueDebug)]
/// struct ApiToken([u8; 32]);
///
/// let t = ApiToken([0; 32]);
/// let out = format!("{t:?}");
/// assert!(out.contains("ApiToken(\"***\")"));
/// ```
///
/// ### Works with generics
///
/// The `Debug` impl includes the instantiated type parameters in the placeholder.
///
/// ```rust
/// # mod vitaminc { pub mod protected { pub use vitaminc_protected::*; } }
/// use vitaminc::protected::OpaqueDebug;
///
/// #[derive(OpaqueDebug)]
/// struct Key<const N: usize>([u8; N]);
///
/// let env = Key::<32>([0u8; 32]);
/// let out = format!("{env:?}");
/// assert!(out.contains("Key<32>(\"***\")"));
/// ```
///
/// ### Enums and unit-like types are supported
///
/// The internal representation is still hidden.
///
/// ```rust
/// # mod vitaminc { pub mod protected { pub use vitaminc_protected::*; } }
/// use vitaminc::protected::OpaqueDebug;
///
/// #[derive(OpaqueDebug)]
/// enum SecretThing {
/// A(u32),
/// B { x: u8, y: u8 },
/// C,
/// }
///
/// let s = SecretThing::B { x: 7, y: 9 };
/// let out = format!("{s:?}");
/// assert!(out.contains("SecretThing::B {x: \"***\", y: \"***\"}"));
/// ```
///
/// ### Marking non-sensitive fields
///
/// You can mark individual fields as non-sensitive using the `#[non_sensitive]` attribute.
/// This is useful when you actually want to include certain fields in the debug output.
///
/// ```rust
/// # mod vitaminc { pub mod protected { pub use vitaminc_protected::*; } }
/// use vitaminc::protected::OpaqueDebug;
///
/// #[derive(OpaqueDebug)]
/// struct HasNonSensitiveField {
/// sensitive: String,
/// #[non_sensitive]
/// value: String,
/// }
///
/// let out = format!(
/// "{:?}",
/// HasNonSensitiveField {
/// sensitive: "do-not-print".into(),
/// value: "ok-to-print".into(),
/// }
/// );
/// assert!(out.contains("HasNonSensitiveField { sensitive: \"***\", value: \"ok-to-print\" }"));
/// ```
///
/// ### Using with Redacted wrapper (optional)
///
/// This is useful to manage external types.
///
/// ```rust
/// # mod vitaminc { pub mod protected { pub use vitaminc_protected::*; } }
/// use core::fmt;
/// use vitaminc::protected::{OpaqueDebug, Redacted};
///
/// let safe = Redacted::new([0u8; 32]);
/// assert_eq!(format!("{:?}", safe), "Redacted<[u8; 32] ***>");
/// ```
///
/// See also [`Redacted`].
///
/// ## Notes
///
/// - The derive intentionally **replaces** any `Debug` you might otherwise derive or write.
/// - The default placeholder is computed with `core::any::type_name::<T>()` at runtime.
/// - The marker trait has no methods; it exists to make trait bounds and wrapper impls
/// straightforward (e.g., a wrapper can `impl<T: OpaqueDebug> Debug for Redacted<T>`).
///
/// ### Feature compatibility
///
/// This module works in `no_std` environments; it only depends on `core`.
///
/// Happy redacting 👋
/// Wrapper type for redacting debug output which implements [`OpaqueDebug`] for all types.
///
/// # Example
///
/// ```
/// # mod vitaminc { pub mod protected { pub use vitaminc_protected::*; } }
/// use vitaminc::protected::Redacted;
///
/// let redacted = Redacted::new([0u8; 32]);
/// assert_eq!(format!("{:?}", redacted), "Redacted<[u8; 32] ***>");
/// ```
///
;