use secrecy::{ExposeSecret, SecretString};
use super::{DeserializeContext, DeserializeParam, WellKnown, WellKnownOption};
use crate::{
error::ErrorWithOrigin,
metadata::{BasicTypes, ParamMetadata, TypeDescription},
value::{StrValue, Value},
};
#[derive(Debug)]
pub struct FromSecretString;
impl<T: From<SecretString> + ExposeSecret<str>> DeserializeParam<T> for FromSecretString {
const EXPECTING: BasicTypes = BasicTypes::STRING;
fn describe(&self, description: &mut TypeDescription) {
description.set_secret();
}
fn deserialize_param(
&self,
ctx: DeserializeContext<'_>,
param: &'static ParamMetadata,
) -> Result<T, ErrorWithOrigin> {
let de = ctx.current_value_deserializer(param.name)?;
let s: SecretString = match de.value() {
Value::String(StrValue::Secret(s)) => s.clone(),
Value::String(StrValue::Plain(s)) => s.clone().into(),
_ => return Err(de.invalid_type("secret string")),
};
Ok(s.into())
}
fn serialize_param(&self, param: &T) -> serde_json::Value {
param.expose_secret().into()
}
}
impl WellKnown for SecretString {
type Deserializer = FromSecretString;
const DE: Self::Deserializer = FromSecretString;
}
impl WellKnownOption for SecretString {}
#[derive(Debug)]
pub struct Secret<De>(pub De);
impl<T, De> DeserializeParam<T> for Secret<De>
where
De: DeserializeParam<T>,
{
const EXPECTING: BasicTypes = {
assert!(
De::EXPECTING.contains(BasicTypes::STRING),
"must be able to deserialize from string"
);
BasicTypes::STRING
};
fn describe(&self, description: &mut TypeDescription) {
self.0.describe(description);
description.set_secret();
}
fn deserialize_param(
&self,
ctx: DeserializeContext<'_>,
param: &'static ParamMetadata,
) -> Result<T, ErrorWithOrigin> {
self.0.deserialize_param(ctx, param)
}
fn serialize_param(&self, param: &T) -> serde_json::Value {
self.0.serialize_param(param)
}
}