eu4save 0.8.2

Ergonomically work with all EU4 saves (ironman and multiplayer)
Documentation
use serde::{de, Deserialize, Deserializer};
use std::marker::PhantomData;
use std::{collections::HashMap, fmt, hash::Hash};

pub(crate) fn deserialize_alternating_key_values<'de, D, K, V>(
    deserializer: D,
) -> Result<HashMap<K, V>, D::Error>
where
    D: Deserializer<'de>,
    K: Deserialize<'de> + Hash + Eq,
    V: Deserialize<'de>,
{
    struct AlternatePairVisitor<K1, V1> {
        marker: PhantomData<HashMap<K1, V1>>,
    }

    impl<'de, K1, V1> de::Visitor<'de> for AlternatePairVisitor<K1, V1>
    where
        K1: Deserialize<'de> + Hash + Eq,
        V1: Deserialize<'de>,
    {
        type Value = HashMap<K1, V1>;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("a map containing key value tuples")
        }

        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
        where
            A: de::MapAccess<'de>,
        {
            let mut result = if let Some(size) = map.size_hint() {
                HashMap::with_capacity(size / 2)
            } else {
                HashMap::new()
            };

            loop {
                let key = if let Some((_key, key_value)) = map.next_entry()? {
                    let _ignore_value: &str = _key;
                    key_value
                } else {
                    return Ok(result);
                };

                let value = if let Some((_value, value_value)) = map.next_entry()? {
                    let _ignore_value: &str = _value;
                    value_value
                } else {
                    return Ok(result);
                };

                result.insert(key, value);
            }
        }
    }

    deserializer.deserialize_map(AlternatePairVisitor {
        marker: PhantomData,
    })
}