use std::fmt;
use std::error::Error;
use std::marker::PhantomData;
use serde_json;
use libserde as serde;
use self::serde::{Serialize, Serializer, Deserializer};
use self::serde::de::DeserializeOwned;
use self::serde::ser::SerializeTuple;
use super::{TyConst, get_ty_const, get_ty_const_key};
pub trait InterSerialize: Serialize + Sized + 'static {
fn inter_serialize<T: Serialize>(t: &T) -> Result<Self, Box<Error>>;
}
impl InterSerialize for serde_json::Value {
fn inter_serialize<T: Serialize>(t: &T) -> Result<Self, Box<Error>> {
serde_json::to_value(t).map_err(Into::into)
}
}
pub trait InterDeserialize: DeserializeOwned + 'static {
fn inter_deserialize<T>(self) -> Result<T, Box<Error>>
where T: DeserializeOwned;
}
impl InterDeserialize for serde_json::Value {
fn inter_deserialize<T>(self) -> Result<T, Box<Error>>
where T: DeserializeOwned
{
serde_json::from_value(self).map_err(Into::into)
}
}
pub trait HasInterDeserialize: 'static {
type InterDeserialize: InterDeserialize;
}
pub trait Trait<S: InterSerialize, U: HasInterDeserialize> {
fn serialize_inner(&self) -> Result<S, Box<Error>>;
fn ty_const_key(&self) -> usize;
}
impl<S, U, T> Trait<S, U> for T
where S: InterSerialize,
U: HasInterDeserialize,
T: Into<U> + Serialize + DeserializeOwned + 'static
{
fn serialize_inner(&self) -> Result<S, Box<Error>> {
S::inter_serialize(self)
}
fn ty_const_key(&self) -> usize {
get_ty_const_key::<TraitObjDeserializer<U>, Self>()
}
}
pub fn serialize<S, U, T, S2>(boxed: &T, s: S2) -> Result<S2::Ok, S2::Error>
where S: InterSerialize,
U: HasInterDeserialize,
T: Trait<S, U> + ?Sized,
S2: Serializer
{
let mut s = s.serialize_tuple(2)?;
s.serialize_element(&boxed.ty_const_key())?;
s.serialize_element(&boxed.serialize_inner()
.map_err(serde::ser::Error::custom)?)?;
s.end()
}
struct TraitObjDeserializer<U>(fn(U::InterDeserialize) -> Result<U, Box<Error>>)
where U: HasInterDeserialize;
trait DeserializeInner<U: HasInterDeserialize> {
fn deserialize_inner(d: U::InterDeserialize) -> Result<U, Box<Error>>;
}
impl<U, T> DeserializeInner<U> for T
where U: HasInterDeserialize,
T: Into<U> + DeserializeOwned + ?Sized + 'static
{
fn deserialize_inner(d: U::InterDeserialize) -> Result<U, Box<Error>> {
d.inter_deserialize::<T>().map(Into::into)
}
}
impl<U, T> TyConst<T> for TraitObjDeserializer<U>
where U: HasInterDeserialize,
T: Into<U> + DeserializeOwned + ?Sized + 'static
{
fn get_data() -> Self {
TraitObjDeserializer(T::deserialize_inner)
}
}
struct Visitor<U>(PhantomData<U>)
where U: HasInterDeserialize;
impl<'de, U> serde::de::Visitor<'de> for Visitor<U>
where U: HasInterDeserialize,
{
type Value = U;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a seq")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>
{
let k = seq.next_element()?
.ok_or(serde::de::Error::missing_field("missing key"))?;
let TraitObjDeserializer(tod) = get_ty_const(k)
.ok_or(serde::de::Error::invalid_value(
serde::de::Unexpected::Unsigned(k as u64), &self))?;
let d = seq.next_element()?
.ok_or(serde::de::Error::missing_field("missing inner object"))?;
tod(d).map_err(serde::de::Error::custom)
}
}
pub fn deserialize<'de, U, D>(d: D) -> Result<U, D::Error>
where D: Deserializer<'de>,
U: HasInterDeserialize
{
d.deserialize_tuple(2, Visitor(PhantomData))
}