use std::fmt;
use serde::ser::SerializeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::meta::{Error, Meta};
use crate::traits::{Empty, FromValue, IntoValue, SkipSerialization};
use crate::value::{Map, Value};
#[derive(Default, Debug, Serialize)]
pub struct MetaTree {
#[serde(rename = "", skip_serializing_if = "Meta::is_empty")]
pub meta: Meta,
#[serde(flatten)]
pub children: MetaMap,
}
impl MetaTree {
fn from_value(value: Annotated<Value>) -> Self {
match value {
Annotated(Some(Value::Object(mut map)), _) => MetaTree {
meta: map
.remove("")
.and_then(|value| {
let value: serde_json::Value = value.into();
serde_json::from_value(value).ok()
})
.unwrap_or_default(),
children: map
.into_iter()
.map(|(k, v)| (k, MetaTree::from_value(v)))
.collect(),
},
_ => MetaTree::default(),
}
}
pub fn has_errors(&self) -> bool {
self.meta.has_errors() || self.children.values().any(MetaTree::has_errors)
}
pub fn is_empty(&self) -> bool {
self.meta.is_empty() && self.children.values().all(MetaTree::is_empty)
}
}
pub type MetaMap = Map<String, MetaTree>;
#[derive(Clone, PartialEq)]
pub struct Annotated<T>(pub Option<T>, pub Meta);
pub struct SerializableAnnotated<'a, T>(pub &'a Annotated<T>);
impl<T: IntoValue> Serialize for SerializableAnnotated<'_, T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize_with_meta(serializer)
}
}
impl<T: fmt::Debug> fmt::Debug for Annotated<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Annotated(Some(ref value), ref meta) => {
if meta.is_empty() {
fmt::Debug::fmt(value, f)
} else {
f.debug_tuple("Annotated").field(value).field(meta).finish()
}
}
Annotated(None, ref meta) => {
if meta.is_empty() {
f.pad("~")
} else {
fmt::Debug::fmt(meta, f)
}
}
}
}
}
impl<T> Annotated<T> {
#[inline]
pub fn new(value: T) -> Self {
Annotated(Some(value), Meta::default())
}
#[inline]
pub fn empty() -> Self {
Annotated(None, Meta::default())
}
pub fn from_error<E>(err: E, value: Option<Value>) -> Self
where
E: Into<Error>,
{
Annotated(None, {
let mut meta = Meta::from_error(err);
meta.set_original_value(value);
meta
})
}
#[inline]
pub fn value(&self) -> Option<&T> {
self.0.as_ref()
}
#[inline]
pub fn value_mut(&mut self) -> &mut Option<T> {
&mut self.0
}
#[inline]
pub fn set_value(&mut self, value: Option<T>) {
self.0 = value;
}
#[inline]
pub fn meta(&self) -> &Meta {
&self.1
}
#[inline]
pub fn meta_mut(&mut self) -> &mut Meta {
&mut self.1
}
#[inline]
pub fn into_value(self) -> Option<T> {
self.0
}
pub fn and_then<F, U, R>(self, f: F) -> Annotated<U>
where
F: FnOnce(T) -> R,
R: Into<Annotated<U>>,
{
if let Some(value) = self.0 {
let Annotated(value, meta) = f(value).into();
Annotated(value, self.1.merge(meta))
} else {
Annotated(None, self.1)
}
}
pub fn map_value<U, F>(self, f: F) -> Annotated<U>
where
F: FnOnce(T) -> U,
{
Annotated(self.0.map(f), self.1)
}
pub fn get_or_insert_with<F>(&mut self, f: F) -> &mut T
where
F: FnOnce() -> T,
{
self.value_mut().get_or_insert_with(f)
}
pub fn merge(&mut self, other: Annotated<T>, block: impl FnOnce(&mut T, T)) {
match (self.value_mut(), other.into_value()) {
(Some(left), Some(right)) => block(left, right),
(None, Some(right)) => self.set_value(Some(right)),
_ => {}
}
}
}
impl<T> Annotated<T>
where
T: AsRef<str>,
{
#[inline]
pub fn as_str(&self) -> Option<&str> {
self.value().map(AsRef::as_ref)
}
}
impl Annotated<Value> {
#[inline]
pub fn as_str(&self) -> Option<&str> {
self.value().and_then(Value::as_str)
}
}
impl<T> Annotated<T>
where
T: Empty,
{
pub fn skip_serialization(&self, behavior: SkipSerialization) -> bool {
if !self.meta().is_empty() {
return false;
}
match behavior {
SkipSerialization::Never => false,
SkipSerialization::Null(_) => self.value().is_none(),
SkipSerialization::Empty(false) => self.value().map_or(true, Empty::is_empty),
SkipSerialization::Empty(true) => self.value().map_or(true, Empty::is_deep_empty),
}
}
}
impl<T> Annotated<T>
where
T: FromValue,
{
pub fn deserialize_with_meta<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
Ok(FromValue::from_value(
match Option::<Value>::deserialize(deserializer)? {
Some(Value::Object(mut map)) => {
let meta_tree = map
.remove("_meta")
.map(MetaTree::from_value)
.unwrap_or_default();
let mut value: Annotated<Value> = Annotated::new(Value::Object(map));
value.attach_meta_tree(meta_tree);
value
}
other => Annotated::from(other),
},
))
}
pub fn from_json(s: &str) -> Result<Self, serde_json::Error> {
Self::deserialize_with_meta(&mut serde_json::Deserializer::from_str(s))
}
pub fn from_json_bytes(b: &[u8]) -> Result<Self, serde_json::Error> {
Self::deserialize_with_meta(&mut serde_json::Deserializer::from_slice(b))
}
}
impl<T> Annotated<T>
where
T: IntoValue,
{
pub fn serialize_with_meta<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut map_ser = serializer.serialize_map(None)?;
let meta_tree = IntoValue::extract_meta_tree(self);
if let Some(value) = self.value() {
use serde::__private::ser::FlatMapSerializer;
IntoValue::serialize_payload(
value,
FlatMapSerializer(&mut map_ser),
SkipSerialization::default(),
)?;
}
if !meta_tree.is_empty() {
map_ser.serialize_key("_meta")?;
map_ser.serialize_value(&meta_tree)?;
}
map_ser.end()
}
pub fn to_json(&self) -> Result<String, serde_json::Error> {
let mut ser = serde_json::Serializer::new(Vec::with_capacity(128));
self.serialize_with_meta(&mut ser)?;
Ok(unsafe { String::from_utf8_unchecked(ser.into_inner()) })
}
pub fn to_json_pretty(&self) -> Result<String, serde_json::Error> {
let mut ser = serde_json::Serializer::pretty(Vec::with_capacity(128));
self.serialize_with_meta(&mut ser)?;
Ok(unsafe { String::from_utf8_unchecked(ser.into_inner()) })
}
pub fn payload_to_json(&self) -> Result<String, serde_json::Error> {
let mut ser = serde_json::Serializer::new(Vec::with_capacity(128));
match self.value() {
Some(value) => {
IntoValue::serialize_payload(value, &mut ser, SkipSerialization::default())?
}
None => ser.serialize_unit()?,
}
Ok(unsafe { String::from_utf8_unchecked(ser.into_inner()) })
}
pub fn payload_to_json_pretty(&self) -> Result<String, serde_json::Error> {
let mut ser = serde_json::Serializer::pretty(Vec::with_capacity(128));
match self.value() {
Some(value) => {
IntoValue::serialize_payload(value, &mut ser, SkipSerialization::default())?
}
None => ser.serialize_unit()?,
}
Ok(unsafe { String::from_utf8_unchecked(ser.into_inner()) })
}
}
impl Annotated<Value> {
fn attach_meta_tree(&mut self, mut meta_tree: MetaTree) {
match self.value_mut() {
Some(Value::Array(items)) => {
for (idx, item) in items.iter_mut().enumerate() {
if let Some(meta_tree) = meta_tree.children.remove(&idx.to_string()) {
item.attach_meta_tree(meta_tree);
}
}
}
Some(Value::Object(items)) => {
for (key, value) in items.iter_mut() {
if let Some(meta_tree) = meta_tree.children.remove(key) {
value.attach_meta_tree(meta_tree);
}
}
}
_ => {}
}
*self.meta_mut() = meta_tree.meta;
}
}
impl<T> From<T> for Annotated<T> {
fn from(t: T) -> Self {
Annotated::new(t)
}
}
impl<T> From<Option<T>> for Annotated<T> {
fn from(option: Option<T>) -> Self {
Annotated(option, Meta::default())
}
}
impl<T> Default for Annotated<T> {
fn default() -> Annotated<T> {
Annotated::empty()
}
}