use async_std::{
net::{IpAddr, SocketAddr},
sync::{Arc, RwLock},
};
use std::collections::BTreeMap;
struct IdMaker {
last: Arc<RwLock<u16>>,
}
impl IdMaker {
async fn curr(&self) -> u16 {
*self.last.read().await
}
async fn incr(&self) -> &Self {
*self.last.write().await += 1;
self
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct Peer {
pub(crate) ip: IpAddr,
pub(crate) port: u16,
}
impl Peer {
pub(crate) fn to_string(&self) -> String {
format!("{}:{}", self.ip, self.port)
}
}
impl From<SocketAddr> for Peer {
fn from(sa: SocketAddr) -> Self {
Self::from(&sa)
}
}
impl From<&SocketAddr> for Peer {
fn from(sa: &SocketAddr) -> Self {
Self {
ip: sa.ip(),
port: sa.port(),
}
}
}
pub(crate) struct AddrTable {
factory: IdMaker,
ips: Arc<RwLock<BTreeMap<u16, Peer>>>,
ids: Arc<RwLock<BTreeMap<Peer, u16>>>,
}
impl AddrTable {
pub(crate) fn new() -> Self {
Self {
factory: IdMaker {
last: Default::default(),
},
ips: Default::default(),
ids: Default::default(),
}
}
pub(crate) async fn set<I: Into<Peer>>(&self, i: I) -> u16 {
let id = self.factory.incr().await.curr().await;
let peer = i.into();
self.ips.write().await.insert(id, peer);
self.ids.write().await.insert(peer, id);
id
}
pub(crate) async fn id(&self, peer: Peer) -> Option<u16> {
self.ids.read().await.get(&peer).cloned()
}
pub(crate) async fn ip(&self, id: u16) -> Option<Peer> {
self.ips.read().await.get(&id).cloned()
}
pub(crate) async fn all(&self) -> Vec<Peer> {
self.ips.read().await.values().cloned().collect()
}
}