use std::panic::Location;
use serde::Serialize;
use crate::{Profile, Provider, Metadata};
use crate::error::{Error, Kind::InvalidType};
use crate::value::{Value, Map, Dict};
#[derive(Debug, Clone)]
pub struct Serialized<T> {
pub value: T,
pub key: Option<String>,
pub profile: Profile,
loc: &'static Location<'static>,
}
impl<T> Serialized<T> {
#[track_caller]
pub fn from<P: Into<Profile>>(value: T, profile: P) -> Serialized<T> {
Serialized {
value,
key: None,
profile: profile.into(),
loc: Location::caller()
}
}
#[track_caller]
pub fn defaults(value: T) -> Serialized<T> {
Self::from(value, Profile::Default)
}
#[track_caller]
pub fn globals(value: T) -> Serialized<T> {
Self::from(value, Profile::Global)
}
#[track_caller]
pub fn default(key: &str, value: T) -> Serialized<T> {
Self::from(value, Profile::Default).key(key)
}
#[track_caller]
pub fn global(key: &str, value: T) -> Serialized<T> {
Self::from(value, Profile::Global).key(key)
}
pub fn profile<P: Into<Profile>>(mut self, profile: P) -> Self {
self.profile = profile.into();
self
}
pub fn key(mut self, key: &str) -> Self {
self.key = Some(key.into());
self
}
}
impl<T: Serialize> Provider for Serialized<T> {
fn metadata(&self) -> Metadata {
Metadata::from(std::any::type_name::<T>(), self.loc)
}
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
let value = Value::serialize(&self.value)?;
let error = InvalidType(value.to_actual(), "map".into());
let dict = match &self.key {
Some(key) => crate::util::nest(key, value).into_dict().ok_or(error)?,
None => value.into_dict().ok_or(error)?,
};
Ok(self.profile.clone().collect(dict))
}
}