polyoxide_venue/
secret.rs1use std::fmt;
4
5#[derive(Clone)]
19pub struct Secret<T>(T);
20
21impl<T> Secret<T> {
22 pub const fn new(value: T) -> Self {
24 Self(value)
25 }
26
27 pub fn expose(&self) -> &T {
29 &self.0
30 }
31}
32
33impl<T> fmt::Debug for Secret<T> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 f.write_str("Secret([REDACTED])")
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[derive(Debug)]
44 #[allow(dead_code)]
45 struct Credentials {
46 key: &'static str,
47 secret: Secret<&'static str>,
48 }
49
50 #[test]
51 fn debug_never_shows_the_value() {
52 let creds = Credentials {
53 key: "public",
54 secret: Secret::new("hunter2"),
55 };
56 let printed = format!("{creds:?} {creds:#?}");
57 assert!(!printed.contains("hunter2"), "{printed}");
58 assert!(printed.contains("public"), "{printed}");
59 assert!(printed.contains("Secret([REDACTED])"), "{printed}");
60 }
61
62 #[test]
63 fn a_clone_holds_the_same_value() {
64 let secret = Secret::new(String::from("hunter2"));
65 assert_eq!(secret.clone().expose(), secret.expose());
66 }
67}