serde_xmlrpc 0.2.2

A simple, no nonsense, XML-RPC serde implementation for Rust
Documentation
use std::collections::BTreeMap;

use serde::de::Visitor;
use serde::forward_to_deserialize_any;

use crate::{Error, Result, Value};

pub struct Deserializer {
    val: Value,
}

impl Deserializer {
    pub fn from_value(input: Value) -> Self {
        Deserializer { val: input }
    }
}

impl<'de> serde::Deserializer<'de> for Deserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        match self.val {
            Value::Int(v) => visitor.visit_i32(v),
            Value::Int64(v) => visitor.visit_i64(v),
            Value::Bool(v) => visitor.visit_bool(v),
            Value::String(v) => visitor.visit_string(v),
            Value::Double(v) => visitor.visit_f64(v),
            Value::DateTime(v) => visitor.visit_string(v.to_string()),
            Value::Base64(v) => visitor.visit_bytes(v.as_slice()),
            Value::Struct(v) => {
                let map_deserializer = MapDeserializer::new(v);
                visitor.visit_map(map_deserializer)
            }
            Value::Array(v) => {
                let seq_deserializer = SeqDeserializer::new(v);
                visitor.visit_seq(seq_deserializer)
            }
            Value::Nil => visitor.visit_none(),
        }
    }

    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
    where
        V: Visitor<'de>,
    {
        if let Value::Nil = self.val {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    forward_to_deserialize_any!(
        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
        byte_buf unit unit_struct newtype_struct seq tuple
        tuple_struct map struct enum identifier ignored_any
    );
}

struct SeqDeserializer {
    iter: std::vec::IntoIter<Value>,
}

impl SeqDeserializer {
    fn new(vec: Vec<Value>) -> Self {
        SeqDeserializer {
            iter: vec.into_iter(),
        }
    }
}

impl<'de> serde::de::SeqAccess<'de> for SeqDeserializer {
    type Error = Error;

    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
    where
        T: serde::de::DeserializeSeed<'de>,
    {
        match self.iter.next() {
            Some(value) => seed.deserialize(Deserializer::from_value(value)).map(Some),
            None => Ok(None),
        }
    }
}

struct MapDeserializer {
    iter: <BTreeMap<String, Value> as IntoIterator>::IntoIter,
    value: Option<Value>,
}

impl MapDeserializer {
    fn new(map: BTreeMap<String, Value>) -> Self {
        MapDeserializer {
            iter: map.into_iter(),
            value: None,
        }
    }
}

impl<'de> serde::de::MapAccess<'de> for MapDeserializer {
    type Error = Error;

    fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
    where
        T: serde::de::DeserializeSeed<'de>,
    {
        match self.iter.next() {
            Some((key, value)) => {
                self.value = Some(value);
                seed.deserialize(Deserializer::from_value(Value::String(key)))
                    .map(Some)
            }
            None => Ok(None),
        }
    }

    fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value>
    where
        T: serde::de::DeserializeSeed<'de>,
    {
        match self.value.take() {
            Some(value) => seed.deserialize(Deserializer::from_value(value)),
            None => Err(serde::de::Error::custom("value is missing")),
        }
    }

    fn size_hint(&self) -> Option<usize> {
        match self.iter.size_hint() {
            (lower, Some(upper)) if lower == upper => Some(upper),
            _ => None,
        }
    }
}

impl<'de, 'a, 'r> serde::Deserialize<'de> for Value {
    fn deserialize<D>(deserializer: D) -> std::result::Result<Value, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        serde_transcode::transcode(deserializer, super::Serializer::new())
            .map_err(|e| serde::de::Error::custom(e))
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    #[derive(Deserialize, Debug, PartialEq)]
    struct Test {
        hello: String,
    }

    #[derive(Deserialize, Debug, PartialEq)]
    struct Test2 {
        val: Option<String>,
    }

    #[test]
    fn test_serde() {
        use std::collections::BTreeMap;
        use std::iter::FromIterator;

        use super::Deserializer;
        use crate::Value;

        let x = Value::Int(42);
        let y = i32::deserialize(Deserializer::from_value(x)).unwrap();
        assert_eq!(y, 42);

        let x = Value::Array(vec![Value::String("hello world".to_string())]);
        let y: Vec<String> = Vec::deserialize(Deserializer::from_value(x)).unwrap();
        assert_eq!(y, vec!["hello world".to_string()]);

        let x = Value::Struct(BTreeMap::from_iter(
            vec![("hello".to_string(), Value::String("world".to_string()))].into_iter(),
        ));
        let y = Test::deserialize(Deserializer::from_value(x)).unwrap();
        assert_eq!(
            y,
            Test {
                hello: "world".to_string(),
            },
        );

        let x = Value::Struct(BTreeMap::new());
        let y = Test2::deserialize(Deserializer::from_value(x)).unwrap();
        assert_eq!(y, Test2 { val: None },);

        let x = Value::Struct(BTreeMap::from_iter(
            vec![("val".to_string(), Value::Nil)].into_iter(),
        ));
        let y = Test2::deserialize(Deserializer::from_value(x)).unwrap();
        assert_eq!(y, Test2 { val: None },);

        let x = Value::Struct(BTreeMap::from_iter(
            vec![("val".to_string(), Value::String("hello".to_string()))].into_iter(),
        ));
        let y = Test2::deserialize(Deserializer::from_value(x)).unwrap();
        assert_eq!(
            y,
            Test2 {
                val: Some("hello".to_string())
            },
        );
    }
}