cycle_map 0.2.0

Implementations of bi-directionally accessible hashmaps
Documentation
use crate::CycleMap;
use core::{
    fmt,
    hash::{BuildHasher, Hash},
    marker::PhantomData,
};
use serde::{
    de::{SeqAccess, Visitor},
    ser::{SerializeSeq, Serializer},
    Deserializer, {Deserialize, Serialize},
};

pub(crate) struct CycleMapVisitor<L, R, S> {
    marker: PhantomData<fn() -> CycleMap<L, R, S>>,
}

impl<L, R, S> CycleMapVisitor<L, R, S>
where
    L: Eq + Hash,
    R: Eq + Hash,
    S: BuildHasher + Clone,
{
    fn new() -> Self {
        CycleMapVisitor {
            marker: PhantomData,
        }
    }
}

impl<'de, L, R, S> Visitor<'de> for CycleMapVisitor<L, R, S>
where
    L: Deserialize<'de> + Eq + Hash,
    R: Deserialize<'de> + Eq + Hash,
    S: BuildHasher + Clone + Default,
{
    type Value = CycleMap<L, R, S>;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("a CycleMap")
    }

    fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
    where
        M: SeqAccess<'de>,
    {
        let mut map: CycleMap<L, R, S> =
            CycleMap::with_capacity_and_hasher(access.size_hint().unwrap_or(0), Default::default());

        while let Some(entry) = access.next_element::<(L, R)>()? {
            map.insert(entry.0, entry.1);
        }

        Ok(map)
    }
}

impl<'de, L, R, S> Deserialize<'de> for CycleMap<L, R, S>
where
    L: Deserialize<'de> + Eq + Hash,
    R: Deserialize<'de> + Eq + Hash,
    S: BuildHasher + Clone + Default,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_seq(CycleMapVisitor::<L, R, S>::new())
    }
}

impl<L, R, H> Serialize for CycleMap<L, R, H>
where
    L: Serialize + Eq + Hash,
    R: Serialize + Eq + Hash,
    H: BuildHasher + Clone,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_seq(Some(self.len()))?;

        for pair in self.iter() {
            map.serialize_element(&pair)?;
        }

        map.end()
    }
}

#[cfg(test)]
mod tests {
    use crate::CycleMap;
    use serde::{Serialize, Deserialize};

    #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Hash, Debug)]
    struct TestingStruct {
        pub(crate) value: u64,
        pub(crate) data: String,
    }

    fn construct_default_map() -> CycleMap<String, TestingStruct> {
        (0..10)
            .map(|i| (i.to_string(), TestingStruct::from_value(i)))
            .collect()
    }

    #[test]
    fn serialize_deserialize_test() {
        let map = construct_default_map();
        let jsonified: String =
            serde_json::to_string(&map).expect("Unable to convert data to json!");
        println!("JSON: {jsonified}");
        let reconsituted: CycleMap<String, TestingStruct> =
            serde_json::from_str(&jsonified).expect("Unable to convert json to hashbag!");
        println!("From json: {reconsituted:?}");
        assert_eq!(map, reconsituted);
    }

    impl TestingStruct {
        pub(crate) fn from_value(value: u64) -> Self {
            Self {
                value,
                data: value.to_string(),
            }
        }
    }
}