askar_storage/protect/
pass_key.rs1use zeroize::Zeroize;
2
3use std::{
4 borrow::Cow,
5 fmt::{self, Debug, Formatter},
6 mem::ManuallyDrop,
7 ops::Deref,
8};
9
10#[derive(Clone, Default)]
12pub struct PassKey<'a>(Option<Cow<'a, str>>);
13
14impl PassKey<'_> {
15 pub fn as_ref(&self) -> PassKey<'_> {
17 PassKey(Some(Cow::Borrowed(&**self)))
18 }
19
20 pub fn empty() -> PassKey<'static> {
22 PassKey(None)
23 }
24
25 pub(crate) fn is_none(&self) -> bool {
26 self.0.is_none()
27 }
28
29 pub fn into_owned(self) -> PassKey<'static> {
31 let mut slf = ManuallyDrop::new(self);
32 let val = slf.0.take();
33 PassKey(match val {
34 None => None,
35 Some(Cow::Borrowed(s)) => Some(Cow::Owned(s.to_string())),
36 Some(Cow::Owned(s)) => Some(Cow::Owned(s)),
37 })
38 }
39}
40
41impl Debug for PassKey<'_> {
42 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
43 if cfg!(test) {
44 f.debug_tuple("PassKey").field(&self.0).finish()
45 } else {
46 f.debug_tuple("PassKey").field(&"<secret>").finish()
47 }
48 }
49}
50
51impl Deref for PassKey<'_> {
52 type Target = str;
53
54 fn deref(&self) -> &str {
55 match self.0.as_ref() {
56 None => "",
57 Some(s) => s.as_ref(),
58 }
59 }
60}
61
62impl Drop for PassKey<'_> {
63 fn drop(&mut self) {
64 self.zeroize();
65 }
66}
67
68impl<'a> From<&'a str> for PassKey<'a> {
69 fn from(inner: &'a str) -> Self {
70 Self(Some(Cow::Borrowed(inner)))
71 }
72}
73
74impl From<String> for PassKey<'_> {
75 fn from(inner: String) -> Self {
76 Self(Some(Cow::Owned(inner)))
77 }
78}
79
80impl<'a> From<Option<&'a str>> for PassKey<'a> {
81 fn from(inner: Option<&'a str>) -> Self {
82 Self(inner.map(Cow::Borrowed))
83 }
84}
85
86impl<'a> PartialEq<PassKey<'a>> for PassKey<'_> {
87 fn eq(&self, other: &PassKey<'a>) -> bool {
88 **self == **other
89 }
90}
91impl Eq for PassKey<'_> {}
92
93impl Zeroize for PassKey<'_> {
94 fn zeroize(&mut self) {
95 if let Some(Cow::Owned(mut s)) = self.0.take() {
96 s.zeroize();
97 }
98 }
99}