1use std::fmt;
4
5#[derive(Clone, PartialEq, Eq)]
10pub struct Secret(String);
11
12impl Secret {
13 pub fn new(value: impl Into<String>) -> Self {
15 Self(value.into())
16 }
17
18 #[must_use]
20 pub fn expose(&self) -> &str {
21 &self.0
22 }
23}
24
25impl fmt::Debug for Secret {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 f.write_str("Secret(***)")
28 }
29}
30
31impl From<String> for Secret {
32 fn from(value: String) -> Self {
33 Self(value)
34 }
35}
36
37impl From<&str> for Secret {
38 fn from(value: &str) -> Self {
39 Self(value.to_owned())
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::Secret;
46
47 #[test]
48 fn debug_output_omits_the_value() {
49 let secret = Secret::new("sandbox-key-value");
50 assert!(!format!("{secret:?}").contains("sandbox-key-value"));
51 assert_eq!(secret.expose(), "sandbox-key-value");
52 }
53}