use log::kv::Source;
use log::kv::{Error, Key, Value, VisitSource};
use serde::ser::SerializeMap;
use serde::{Serialize, Serializer};

pub struct KeyValueSource<'a>(pub &'a dyn Source);

pub struct KeyValueVisitor<'a, S: Serializer> {
    serialize_map: &'a mut S::SerializeMap
}

impl<S: Serializer> VisitSource<'_> for KeyValueVisitor<'_, S> {
    fn visit_pair<'kvs>(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
        self.serialize_map
            .serialize_entry(&key, &value)
            .map_err(|e| Error::boxed(e.to_string()))?;
        Ok(())
    }
}

impl Serialize for KeyValueSource<'_> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer
    {
        let mut serialize_map = serializer.serialize_map(Some(self.0.count()))?;
        self.0.visit(&mut KeyValueVisitor::<S> {
            serialize_map: &mut serialize_map,
        }).map_err(serde::ser::Error::custom)?;
        serialize_map.end()
    }
}