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
use std::fmt::{Debug, Formatter, Result};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Clone)]
// This tagging allows deserializers to know whether the secret is a string or bytes.
// This is especially necessary for languages where strings and bytes are treated very similarly.
#[serde(tag = "kind", content = "value")]
pub enum SecretValue {
String(String),
Bytes(Vec<u8>),
}
impl SecretValue {
/// Utility function for retrieving a string slice from this [`SecretValue`], if possible.
///
/// If the secret does not contain a string, `None` is returned
#[must_use]
pub fn as_string(&self) -> Option<&str> {
match self {
SecretValue::String(s) => Some(s),
SecretValue::Bytes(_) => None,
}
}
/// Utility function for retrieving bytes from this [`SecretValue`], if possible.
///
/// If the secret does not contain bytes, `None` is returned
#[must_use]
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
SecretValue::String(_) => None,
SecretValue::Bytes(b) => Some(b),
}
}
}
/// Debug implementation that doesn't log the secret value
impl Debug for SecretValue {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self {
SecretValue::String(_) => write!(f, "string(redacted)"),
SecretValue::Bytes(_) => write!(f, "bytes(redacted)"),
}
}
}