use {
    problemo::{common::*, *},
    serde::{Deserialize, de},
};

// This example shows how to use Problemo for a serde Deserializer implementation.
// It requires the "serde" feature to be enabled.

// The challenge is that serde requires the error to implement serde::de::Error,
// in addition to std::error::Error.

// To support these traits we provide a SerdeProblem wrapper. Note, however, that you want to
// use some care when converting it to/from a Problem in order to preserve the causation chain.

// Implementing a serde Serializer would use the same technique.

fn deserialize_string<DeserializeT>(source: &str) -> Result<DeserializeT, Problem>
where
    DeserializeT: de::DeserializeOwned,
{
    // Note that we *do not* want to use into_problem() here, as it would collapse our causation chain
    DeserializeT::deserialize(StringDeserializer::new(source.into())).from_serde_problem()
}

fn main() {
    match deserialize_string::<Person>("some data") {
        Ok(person) => println!("name: {}, age: {}", person.name, person.age),
        Err(problem) => println!("{}", problem),
    }
}

//
// Person
//

#[derive(Deserialize)]
struct Person {
    pub name: String,
    pub age: u8,
}

//
// StringDeserializer
//

pub struct StringDeserializer {
    _source: String,
}

impl StringDeserializer {
    /// Constructor.
    pub fn new(source: String) -> Self {
        StringDeserializer { _source: source }
    }
}

// This is just an example that returns UnsupportedError for *everything*.

// We're using into_serde_deserialize_problem(), which will handle the conversion via
// a DeserializeError.

impl<'de> de::Deserializer<'de> for StringDeserializer {
    // SerdeProblem is a special wrapper that implements serde::ser::Error and serde::de::Error
    type Error = SerdeProblem;

    fn deserialize_any<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_any").into_serde_deserialize_problem())
    }

    fn deserialize_bool<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_bool").into_serde_deserialize_problem())
    }

    fn deserialize_i8<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_i8").into_serde_deserialize_problem())
    }

    fn deserialize_i16<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_i16").into_serde_deserialize_problem())
    }

    fn deserialize_i32<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_i32").into_serde_deserialize_problem())
    }

    fn deserialize_i64<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_i64").into_serde_deserialize_problem())
    }

    fn deserialize_u8<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_u8").into_serde_deserialize_problem())
    }

    fn deserialize_u16<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_u16").into_serde_deserialize_problem())
    }

    fn deserialize_u32<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_u32").into_serde_deserialize_problem())
    }

    fn deserialize_u64<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_u64").into_serde_deserialize_problem())
    }

    fn deserialize_f32<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_f32").into_serde_deserialize_problem())
    }

    fn deserialize_f64<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_f64").into_serde_deserialize_problem())
    }

    fn deserialize_char<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_char").into_serde_deserialize_problem())
    }

    fn deserialize_str<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_str").into_serde_deserialize_problem())
    }

    fn deserialize_string<VisitorT>(
        self,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_string").into_serde_deserialize_problem())
    }

    fn deserialize_bytes<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_bytes").into_serde_deserialize_problem())
    }

    fn deserialize_byte_buf<VisitorT>(
        self,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_byte_buf").into_serde_deserialize_problem())
    }

    fn deserialize_option<VisitorT>(
        self,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_option").into_serde_deserialize_problem())
    }

    fn deserialize_unit<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_unit").into_serde_deserialize_problem())
    }

    fn deserialize_unit_struct<VisitorT>(
        self,
        _name: &'static str,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_unit_struct").into_serde_deserialize_problem())
    }

    fn deserialize_newtype_struct<VisitorT>(
        self,
        _name: &'static str,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_newtype_struct").into_serde_deserialize_problem())
    }

    fn deserialize_seq<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_seq").into_serde_deserialize_problem())
    }

    fn deserialize_tuple<VisitorT>(
        self,
        _len: usize,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_tuple").into_serde_deserialize_problem())
    }

    fn deserialize_tuple_struct<VisitorT>(
        self,
        _name: &'static str,
        _len: usize,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_tuple_struct").into_serde_deserialize_problem())
    }

    fn deserialize_map<VisitorT>(self, _visitor: VisitorT) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_map").into_serde_deserialize_problem())
    }

    fn deserialize_struct<VisitorT>(
        self,
        _name: &'static str,
        _fields: &'static [&'static str],
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_struct").into_serde_deserialize_problem())
    }

    fn deserialize_enum<VisitorT>(
        self,
        _name: &'static str,
        _variants: &'static [&'static str],
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_enum").into_serde_deserialize_problem())
    }

    fn deserialize_identifier<VisitorT>(
        self,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_identifier").into_serde_deserialize_problem())
    }

    fn deserialize_ignored_any<VisitorT>(
        self,
        _visitor: VisitorT,
    ) -> Result<VisitorT::Value, Self::Error>
    where
        VisitorT: de::Visitor<'de>,
    {
        Err(UnsupportedError::new("deserialize_ignored_any").into_serde_deserialize_problem())
    }
}
