1use core::{convert::Infallible, fmt::Debug, str::FromStr};
2
3use crate::{GString, GStringError, NoValidation, Validator};
4
5#[derive(Clone, PartialEq, Eq)]
17pub struct GSecret<
18 V: Validator = NoValidation,
19 const MIN: usize = 0,
20 const MAX: usize = 255,
21 const ASCII_ONLY: bool = false,
22> {
23 inner: GString<V, MIN, MAX, ASCII_ONLY>,
24}
25
26impl GSecret {
27 #[inline]
29 pub fn try_default<S>(secret: S) -> Result<Self, GStringError<Infallible>>
30 where
31 S: AsRef<str>,
32 {
33 Ok(Self {
34 inner: GString::try_default(secret)?,
35 })
36 }
37}
38
39impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool>
40 GSecret<V, MIN, MAX, ASCII_ONLY>
41{
42 #[inline]
44 pub fn try_new<S>(secret: S) -> Result<Self, GStringError<V::Err>>
45 where
46 S: AsRef<str>,
47 {
48 Ok(Self {
49 inner: GString::<V, MIN, MAX, ASCII_ONLY>::try_new(secret)?,
50 })
51 }
52
53 pub fn reveal<R>(&self, func: impl FnOnce(&str) -> R) -> R {
63 func(self.inner.as_str())
64 }
65
66 #[inline]
70 pub fn zeroize(&mut self) {
71 self.inner.zeroize();
72 }
73}
74
75impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> Drop
76 for GSecret<V, MIN, MAX, ASCII_ONLY>
77{
78 fn drop(&mut self) {
79 self.inner.zeroize();
80 }
81}
82
83impl<V, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> zeroize::Zeroize
84 for GSecret<V, MIN, MAX, ASCII_ONLY>
85where
86 V: Validator,
87{
88 fn zeroize(&mut self) {
89 self.inner.zeroize();
90 }
91}
92
93impl<V, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> zeroize::ZeroizeOnDrop
94 for GSecret<V, MIN, MAX, ASCII_ONLY>
95where
96 V: Validator,
97{
98}
99
100impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> Debug
101 for GSecret<V, MIN, MAX, ASCII_ONLY>
102{
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 write!(f, "GSecret(<REDACTED>)")
105 }
106}
107
108impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> FromStr
109 for GSecret<V, MIN, MAX, ASCII_ONLY>
110{
111 type Err = GStringError<V::Err>;
112
113 fn from_str(s: &str) -> Result<Self, Self::Err> {
114 let secret = GSecret::try_new(s)?;
115
116 Ok(secret)
117 }
118}
119
120impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> TryFrom<&str>
121 for GSecret<V, MIN, MAX, ASCII_ONLY>
122{
123 type Error = GStringError<V::Err>;
124
125 fn try_from(value: &str) -> Result<Self, Self::Error> {
126 let secret = GSecret::try_new(value)?;
127
128 Ok(secret)
129 }
130}
131
132#[cfg(feature = "alloc")]
133extern crate alloc;
134
135#[cfg(feature = "alloc")]
136use alloc::string::String;
137
138#[cfg(feature = "alloc")]
139impl<V, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> TryFrom<String>
140 for GSecret<V, MIN, MAX, ASCII_ONLY>
141where
142 V: Validator,
143{
144 type Error = GStringError<V::Err>;
145
146 fn try_from(mut value: String) -> Result<Self, Self::Error> {
147 use zeroize::Zeroize;
148
149 let secret = GSecret::try_new(&value);
150
151 value.zeroize();
152
153 secret
154 }
155}
156
157impl<
158 GSTRINGV: Validator,
159 GSECRETV: Validator,
160 const MIN: usize,
161 const MAX: usize,
162 const ASCII_ONLY: bool,
163> TryFrom<GString<GSTRINGV, MIN, MAX, ASCII_ONLY>> for GSecret<GSECRETV, MIN, MAX, ASCII_ONLY>
164{
165 type Error = GStringError<GSECRETV::Err>;
166
167 fn try_from(value: GString<GSTRINGV, MIN, MAX, ASCII_ONLY>) -> Result<Self, Self::Error> {
168 Self::try_new(value.as_str())
169 }
170}
171
172impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> core::hash::Hash
173 for GSecret<V, MIN, MAX, ASCII_ONLY>
174{
175 #[inline]
176 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
177 self.inner.hash(state)
178 }
179}