use async_std::net::SocketAddr;
use std::{collections::BTreeSet, time::SystemTime};
use serde::{Deserialize, Serialize};
use crate::topic::{InterestLevel, Proximity, Subscription, Subscriptions, Topic};
use crate::id::NetworkID;
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct KnownPeer {
pub(crate) id: NetworkID,
pub(crate) address: Option<SocketAddr>,
pub(crate) subscriptions: Subscriptions,
pub(crate) subscribers: BTreeSet<NetworkID>,
pub(crate) last_gossip: SystemTime,
}
impl KnownPeer {
fn new(id: NetworkID) -> Self {
KnownPeer {
id,
address: None,
subscriptions: Subscriptions::default(),
subscribers: BTreeSet::new(),
last_gossip: SystemTime::now(),
}
}
pub fn new_with(id: NetworkID, address: SocketAddr) -> Self {
KnownPeer {
id,
address: Some(address),
subscriptions: Subscriptions::default(),
subscribers: BTreeSet::new(),
last_gossip: SystemTime::now(),
}
}
pub fn id(&self) -> &NetworkID {
&self.id
}
pub fn address(&self) -> &Option<SocketAddr> {
&self.address
}
pub fn subscriptions(&self) -> impl Iterator<Item = (&Topic, &InterestLevel)> {
self.subscriptions.iter()
}
pub fn subscribers(&self) -> impl Iterator<Item = &NetworkID> {
self.subscribers.iter()
}
pub fn add_subscription(&mut self, subscription: Subscription) -> Option<InterestLevel> {
self.subscriptions.add(subscription)
}
pub fn remove_subscription(&mut self, topic: Topic) -> Option<InterestLevel> {
self.subscriptions.remove(topic)
}
pub fn common_subscriptions<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = &'a Topic> {
self.subscriptions
.common_subscriptions(&other.subscriptions)
}
pub fn common_subscribers<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = &'a NetworkID> {
self.subscribers.intersection(&other.subscribers)
}
pub fn proximity(&self, other: &Self) -> Proximity {
self.subscriptions.proximity_to(&other.subscriptions)
}
}
#[cfg(test)]
mod test {
use super::*;
use quickcheck::{Arbitrary, Gen};
impl Arbitrary for KnownPeer {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
use std::ops::Sub;
let address: Option<SocketAddr> = Arbitrary::arbitrary(g);
let id = NetworkID::arbitrary(g);
KnownPeer {
id,
address,
subscriptions: Subscriptions::arbitrary(g),
subscribers: Arbitrary::arbitrary(g),
last_gossip: SystemTime::now()
.sub(std::time::Duration::new(u32::arbitrary(g) as u64, 0)),
}
}
}
}