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
use zeroize::Zeroize;
use std::{
borrow::Cow,
fmt::{self, Debug, Formatter},
mem::ManuallyDrop,
ops::Deref,
};
#[derive(Clone)]
pub struct PassKey<'a>(Option<Cow<'a, str>>);
impl PassKey<'_> {
pub fn as_ref(&self) -> PassKey<'_> {
PassKey(Some(Cow::Borrowed(&**self)))
}
pub fn empty() -> PassKey<'static> {
PassKey(None)
}
pub(crate) fn is_none(&self) -> bool {
self.0.is_none()
}
pub(crate) fn into_owned(self) -> PassKey<'static> {
let mut slf = ManuallyDrop::new(self);
let val = slf.0.take();
PassKey(match val {
None => None,
Some(Cow::Borrowed(s)) => Some(Cow::Owned(s.to_string())),
Some(Cow::Owned(s)) => Some(Cow::Owned(s)),
})
}
}
impl Debug for PassKey<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if cfg!(test) {
f.debug_tuple("PassKey").field(&*self).finish()
} else {
f.debug_tuple("PassKey").field(&"<secret>").finish()
}
}
}
impl Default for PassKey<'_> {
fn default() -> Self {
Self(None)
}
}
impl Deref for PassKey<'_> {
type Target = str;
fn deref(&self) -> &str {
match self.0.as_ref() {
None => "",
Some(s) => s.as_ref(),
}
}
}
impl Drop for PassKey<'_> {
fn drop(&mut self) {
self.zeroize();
}
}
impl<'a> From<&'a str> for PassKey<'a> {
fn from(inner: &'a str) -> Self {
Self(Some(Cow::Borrowed(inner)))
}
}
impl From<String> for PassKey<'_> {
fn from(inner: String) -> Self {
Self(Some(Cow::Owned(inner)))
}
}
impl<'a> From<Option<&'a str>> for PassKey<'a> {
fn from(inner: Option<&'a str>) -> Self {
Self(inner.map(Cow::Borrowed))
}
}
impl<'a, 'b> PartialEq<PassKey<'b>> for PassKey<'a> {
fn eq(&self, other: &PassKey<'b>) -> bool {
&**self == &**other
}
}
impl Eq for PassKey<'_> {}
impl Zeroize for PassKey<'_> {
fn zeroize(&mut self) {
match self.0.take() {
Some(Cow::Owned(mut s)) => {
s.zeroize();
}
_ => (),
}
}
}