secret_vault_value/
value_serde.rs

1use crate::*;
2use serde::de::{self, Visitor};
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use zeroize::Zeroize;
5
6impl SecretValue {
7    pub fn expose_json_value_as<T>(&self) -> serde_json::Result<T>
8    where
9        for<'de> T: Deserialize<'de> + Zeroize,
10    {
11        serde_json::from_slice(self.ref_sensitive_value())
12    }
13}
14
15impl Serialize for SecretValue {
16    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
17    where
18        S: Serializer,
19    {
20        serializer.serialize_str(
21            String::from_utf8(self.ref_sensitive_value().clone())
22                .map_err(serde::ser::Error::custom)?
23                .as_str(),
24        )
25    }
26}
27
28struct SecretValueVisitor;
29
30#[allow(clippy::needless_lifetimes)]
31impl<'de> Visitor<'de> for SecretValueVisitor {
32    type Value = SecretValue;
33
34    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
35        formatter.write_str("a string expected as a secret value")
36    }
37
38    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
39    where
40        E: de::Error,
41    {
42        Ok(SecretValue::new(value.as_bytes().to_vec()))
43    }
44
45    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
46    where
47        E: de::Error,
48    {
49        Ok(SecretValue::new(value.as_bytes().to_vec()))
50    }
51
52    fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
53    where
54        E: de::Error,
55    {
56        Ok(SecretValue::new(value.to_vec()))
57    }
58
59    fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Self::Value, E>
60    where
61        E: de::Error,
62    {
63        Ok(SecretValue::new(value))
64    }
65}
66
67impl<'de> Deserialize<'de> for SecretValue {
68    fn deserialize<D>(deserializer: D) -> Result<SecretValue, D::Error>
69    where
70        D: Deserializer<'de>,
71    {
72        deserializer.deserialize_string(SecretValueVisitor)
73    }
74}
75
76#[cfg(test)]
77mod test {
78    use super::*;
79    use proptest::prelude::*;
80
81    proptest! {
82        #[test]
83        fn serialize_as_string(mock_secret in "[a-zA-Z0-9]*") {
84            let mock_secret_vec = mock_secret.as_bytes().to_vec();
85            let secret_value = SecretValue::new(mock_secret_vec);
86            let test_serialized_string = serde_json::to_string(&secret_value).unwrap();
87            assert_eq!(test_serialized_string, format!("\"{}\"",mock_secret));
88        }
89
90        #[test]
91        fn deserialize_from_string(mock_secret in "[a-zA-Z0-9]*") {
92            let mock_secret_quoted = format!("\"{}\"",mock_secret);
93            let secret_value: SecretValue = serde_json::from_str(&mock_secret_quoted).unwrap();
94            assert_eq!(String::from_utf8(secret_value.ref_sensitive_value().clone()).unwrap(), mock_secret);
95        }
96    }
97
98    #[test]
99    fn deserialize_embedded_json() {
100        #[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Zeroize)]
101        struct TestJson {
102            pub test_field: String,
103        }
104        let mock_json_struct = TestJson {
105            test_field: "TestValue".into(),
106        };
107
108        let secret_value: SecretValue = serde_json::to_string(&mock_json_struct).unwrap().into();
109
110        assert_eq!(
111            secret_value.expose_json_value_as::<TestJson>().unwrap(),
112            mock_json_struct
113        );
114    }
115}