use std::{collections::HashMap, borrow::Borrow, hash::Hash, marker::PhantomData}; use serde::{de::Visitor, Deserialize, Deserializer}; use crate::supervisor::Link; #[derive(Debug)] pub struct Linkmap { to: HashMap, from: HashMap>, } impl Linkmap { pub fn with_capacity(capacity: usize) -> Self { Self { to: HashMap::with_capacity(capacity), from: HashMap::with_capacity(capacity), } } pub fn get_link(&self, channel: &K) -> Option<&Link> where T: Borrow, K: Hash + Eq + ?Sized { self.to.get(channel) } pub fn get_channels(&self, link: &Link) -> &[T] { self.from.get(link).map_or(&[], Vec::as_slice) } pub fn insert(&mut self, link: Link, channel: T) { self.to.insert(channel.clone(), link.clone()); self.from.entry(link) .or_insert(Vec::with_capacity(1)) .push(channel); } pub fn iter_channels(&self) -> impl Iterator { self.to.keys() } } impl FromIterator<(T, Link)> for Linkmap { fn from_iter>(iter: I) -> Self { let to: HashMap = iter.into_iter().collect(); let mut from = HashMap::with_capacity(to.len()); for (k, v) in &to { from.entry(v.clone()) .or_insert(Vec::with_capacity(1)) .push(k.clone()); } Self { to, from } } } struct LinkmapVisitor { _phantom: PhantomData, } impl <'de, T> Visitor<'de> for LinkmapVisitor where T: Eq + Hash + Clone + Deserialize<'de> { type Value = Linkmap; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { write!(formatter, "a linkmap")?; Ok(()) } fn visit_map(self, mut access: A) -> Result where A: serde::de::MapAccess<'de>, { let mut map = Linkmap::with_capacity(access.size_hint().unwrap_or(0)); while let Some((channel, link)) = access.next_entry()? { map.insert(link, channel); } Ok(map) } } impl <'de, T> Deserialize<'de> for Linkmap where T: Eq + Hash + Clone + Deserialize<'de> { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { deserializer.deserialize_map(LinkmapVisitor { _phantom: PhantomData }) } }