use hashbrown::HashMap;
use serde::{Deserialize, Serialize};
use crate::topic::{
Topic,
InterestLevel,
PriorityScore,
Proximity,
ProximityScore
};
#[derive(Clone, Debug)]
pub struct Subscription {
pub topic: Topic,
pub interest_level: InterestLevel,
}
impl Subscription {
pub fn new(topic: Topic, interest_level: InterestLevel) -> Self {
Subscription {
topic,
interest_level,
}
}
}
impl PartialEq<Topic> for Subscription {
fn eq(&self, topic: &Topic) -> bool {
&self.topic == topic
}
}
impl PartialEq<Self> for Subscription {
fn eq(&self, other: &Self) -> bool {
self.topic == other.topic
}
}
impl Eq for Subscription {}
impl PartialOrd<Topic> for Subscription {
fn partial_cmp(&self, topic: &Topic) -> Option<std::cmp::Ordering> {
self.topic.partial_cmp(topic)
}
}
impl PartialOrd<Self> for Subscription {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.topic.partial_cmp(&other.topic)
}
}
impl Ord for Subscription {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.topic.cmp(&other.topic)
}
}
impl std::hash::Hash for Subscription {
fn hash<H>(&self, state: &mut H)
where
H: std::hash::Hasher,
{
std::hash::Hash::hash(&self.topic, state)
}
}
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Subscriptions(HashMap<Topic, InterestLevel>);
impl Default for Subscriptions {
fn default() -> Self {
Subscriptions(HashMap::default())
}
}
impl Subscriptions {
pub fn add(&mut self, subscription: Subscription) -> Option<InterestLevel> {
self.0
.insert(subscription.topic, subscription.interest_level)
}
pub fn contains(&self, topic: Topic) -> bool {
self.0.contains_key(&topic)
}
pub fn remove(&mut self, subscription: Topic) -> Option<InterestLevel> {
self.0.remove(&subscription)
}
pub fn topics(&self) -> impl Iterator<Item = &Topic> {
self.0.keys()
}
pub fn iter(&self) -> impl Iterator<Item = (&Topic, &InterestLevel)> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&Topic, &mut InterestLevel)> {
self.0.iter_mut()
}
pub fn common_subscriptions<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = &'a Topic> {
self.0
.keys()
.filter(move |topic| other.0.contains_key(topic))
}
pub fn proximity_to(&self, other: &Self) -> Proximity {
let mut priority_score = 0;
let mut proximity_score = 0;
for (subscription, interest_level) in self.iter() {
if let Some(other_interest_level) = other.0.get(subscription) {
proximity_score += 1;
priority_score += interest_level.priority_score(*other_interest_level);
}
}
Proximity {
proximity: ProximityScore(proximity_score),
priority: PriorityScore(priority_score),
}
}
}