use std::fmt::Display;
use crate::{error::ErrorInner, Error};
pub fn into_deserializer<'de, T>(src: T) -> <T as serde::de::IntoDeserializer<'de>>::Deserializer
where
T: serde::de::IntoDeserializer<'de>,
{
src.into_deserializer()
}
pub fn unwrap_or_missing_value_err<T>(value: Option<T>, path: &str) -> Result<T, Error> {
match value {
Some(v) => Ok(v),
None => Err(ErrorInner::MissingValue(path.into()).into()),
}
}
pub fn map_err_prefix_path<T>(res: Result<T, Error>, prefix: &str) -> Result<T, Error> {
res.map_err(|e| {
if let ErrorInner::MissingValue(path) = &*e.inner {
ErrorInner::MissingValue(format!("{prefix}.{path}")).into()
} else {
e
}
})
}
pub fn validate_field<T, E: Display>(
t: &T,
validate: &dyn Fn(&T) -> Result<(), E>,
) -> Result<(), Error> {
validate(t).map_err(Error::field_validation)
}
pub fn validate_struct<T, E: Display>(
t: &T,
validate: &dyn Fn(&T) -> Result<(), E>,
struct_name: &'static str,
) -> Result<(), Error> {
validate(t).map_err(|msg| ErrorInner::StructValidation {
name: struct_name.into(),
msg: msg.to_string()
}.into())
}
macro_rules! get_env_var {
($key:expr, $field:expr) => {
match std::env::var($key) {
Err(std::env::VarError::NotPresent) => return Ok(None),
Err(std::env::VarError::NotUnicode(_)) => {
let err = ErrorInner::EnvNotUnicode {
key: $key.into(),
field: $field.into(),
};
return Err(err.into());
}
Ok(s) => s,
}
};
}
pub fn from_env<T>(
key: &str,
field: &str,
deserialize: fn(crate::env::Deserializer) -> Result<T, crate::env::DeError>,
) -> Result<Option<T>, Error> {
let s = get_env_var!(key, field);
let is_empty = s.is_empty();
match deserialize(crate::env::Deserializer::new(s)) {
Ok(v) => Ok(Some(v)),
Err(_) if is_empty => Ok(None),
Err(e) => Err(ErrorInner::EnvDeserialization {
key: key.into(),
field: field.into(),
msg: e.0,
}.into()),
}
}
pub fn from_env_with_parser<T, E: std::error::Error + Send + Sync + 'static, E2: Display>(
key: &str,
field: &str,
parse: fn(&str) -> Result<T, E>,
validate: fn(&T) -> Result<(), E2>,
) -> Result<Option<T>, Error> {
let v = get_env_var!(key, field);
let is_empty = v.is_empty();
match parse(&v) {
Ok(v) => {
match validate(&v).map_err(Error::field_validation) {
Ok(()) => Ok(Some(v)),
Err(_) if is_empty => Ok(None),
Err(e) => Err(e),
}
},
Err(_) if is_empty => Ok(None),
Err(err) => Err(
ErrorInner::EnvParseError {
field: field.to_owned(),
key: key.to_owned(),
err: Box::new(err),
}.into()
),
}
}
pub struct ArrayIntoDeserializer<T, const N: usize>(pub [T; N]);
impl<'de, T, E, const N: usize> serde::de::IntoDeserializer<'de, E> for ArrayIntoDeserializer<T, N>
where
T: serde::de::IntoDeserializer<'de, E>,
E: serde::de::Error,
{
type Deserializer = serde::de::value::SeqDeserializer<std::array::IntoIter<T, N>, E>;
fn into_deserializer(self) -> Self::Deserializer {
serde::de::value::SeqDeserializer::new(self.0.into_iter())
}
}
pub struct MapIntoDeserializer<K, V>(pub Vec<(K, V)>);
impl<'de, K, V, E> serde::de::IntoDeserializer<'de, E> for MapIntoDeserializer<K, V>
where
K: serde::de::IntoDeserializer<'de, E>,
V: serde::de::IntoDeserializer<'de, E>,
E: serde::de::Error,
{
type Deserializer = serde::de::value::MapDeserializer<'de, std::vec::IntoIter<(K, V)>, E>;
fn into_deserializer(self) -> Self::Deserializer {
serde::de::value::MapDeserializer::new(self.0.into_iter())
}
}