abridged/src/linkmap.rs

90 lines
2.2 KiB
Rust

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<T: Hash + Eq> {
to: HashMap<T, Link>,
from: HashMap<Link, Vec<T>>,
}
impl <T: Hash + Eq + Clone> Linkmap<T> {
pub fn with_capacity(capacity: usize) -> Self {
Self {
to: HashMap::with_capacity(capacity),
from: HashMap::with_capacity(capacity),
}
}
pub fn get_link<K>(&self, channel: &K) -> Option<&Link>
where T: Borrow<K>, 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<Item=&T> {
self.to.keys()
}
}
impl <T: Hash + Eq + Clone> FromIterator<(T, Link)> for Linkmap<T> {
fn from_iter<I: IntoIterator<Item=(T, Link)>>(iter: I) -> Self {
let to: HashMap<T, Link> = 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<T> {
_phantom: PhantomData<T>,
}
impl <'de, T> Visitor<'de> for LinkmapVisitor<T>
where T: Eq + Hash + Clone + Deserialize<'de> {
type Value = Linkmap<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "a linkmap")?;
Ok(())
}
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
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<T>
where T: Eq + Hash + Clone + Deserialize<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
deserializer.deserialize_map(LinkmapVisitor { _phantom: PhantomData })
}
}