1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![cfg_attr(not(feature = "std"), no_std)]
4#![forbid(unsafe_code)]
5
6#[cfg(feature = "std")]
7mod error;
8#[cfg(feature = "fake")]
9mod fake;
10mod ops;
11#[cfg(feature = "serde")]
12pub mod serde;
13#[cfg(feature = "zeroize")]
14mod zeroize;
15
16#[cfg(feature = "serde")]
17pub use crate::serde::expose_secret;
18
19use core::{any::type_name, fmt, str::FromStr};
20
21#[derive(Default, Hash, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
23#[repr(transparent)]
24pub struct Secret<T: ?Sized>(T);
25
26impl<T> Secret<T> {
27 #[inline]
29 #[must_use = "the secret will be dropped if not used"]
30 pub const fn new(secret: T) -> Self {
31 Self(secret)
32 }
33 #[inline]
34 #[must_use]
35 pub fn from(secret: impl Into<T>) -> Self {
36 Self(secret.into())
37 }
38 #[inline]
39 pub fn try_from<U: TryInto<T>>(secret: U) -> Result<Self, Secret<U::Error>> {
40 secret.try_into().map(Self).map_err(Secret)
41 }
42 #[inline]
44 #[must_use = "expose_secret does nothing unless used"]
45 pub const fn expose_secret(&self) -> &T {
46 &self.0
47 }
48}
49
50impl<T> From<T> for Secret<T> {
51 #[inline]
52 fn from(secret: T) -> Self {
53 Self::new(secret)
54 }
55}
56
57impl<T> fmt::Debug for Secret<T> {
58 #[inline]
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 write!(f, "[REDACTED {}]", type_name::<T>())
61 }
62}
63
64impl<T: FromStr> FromStr for Secret<T> {
65 type Err = Secret<T::Err>;
66
67 #[inline]
68 fn from_str(s: &str) -> Result<Self, Self::Err> {
69 s.parse().map(Self).map_err(Secret)
70 }
71}
72
73impl<T> From<Option<Secret<T>>> for Secret<Option<T>> {
74 #[inline]
75 fn from(secret: Option<Secret<T>>) -> Self {
76 Self(secret.map(|Secret(s)| s))
77 }
78}
79
80impl<T, E> From<Result<Secret<T>, E>> for Secret<Result<T, E>> {
81 #[inline]
82 fn from(secret: Result<Secret<T>, E>) -> Self {
83 Self(secret.map(|Secret(s)| s))
84 }
85}
86
87impl<T, E> From<Result<T, Secret<E>>> for Secret<Result<T, E>> {
88 #[inline]
89 fn from(secret: Result<T, Secret<E>>) -> Self {
90 Self(secret.map_err(|Secret(s)| s))
91 }
92}
93
94impl<T, E> From<Result<Secret<T>, Secret<E>>> for Secret<Result<T, E>> {
95 #[inline]
96 fn from(secret: Result<Secret<T>, Secret<E>>) -> Self {
97 Self(secret.map(|Secret(s)| s).map_err(|Secret(s)| s))
98 }
99}
100
101impl<S: FromIterator<T>, T> FromIterator<Secret<T>> for Secret<S> {
102 #[inline]
103 fn from_iter<I: IntoIterator<Item = Secret<T>>>(iter: I) -> Self {
104 Self(S::from_iter(iter.into_iter().map(|Secret(s)| s)))
105 }
106}