use std::fmt;
use crate::{
multiaddr::{self, Multiaddr},
peer_id::PeerId,
Error, Result,
};
pub struct AddrInfo {
peer_id: PeerId,
addrs: Vec<Multiaddr>,
}
impl fmt::Display for AddrInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let addrs = {
let iter = self.addrs.iter().filter_map(|a| a.to_text().ok());
let addrs: Vec<String> = iter.collect();
addrs.join(",")
};
write!(f, "{{{} : {}}}", self.peer_id, addrs)
}
}
impl AddrInfo {
pub fn from_p2p_multiaddrs(addrs: Vec<Multiaddr>) -> Result<Vec<AddrInfo>> {
let mut addr_infos: Vec<AddrInfo> = vec![];
for addr in addrs.into_iter() {
let mut new_a = Self::from_p2p_multiaddr(addr)?;
let off = {
let mut iter = addr_infos.iter().enumerate();
loop {
match iter.next() {
Some((i, a)) if new_a.peer_id == a.peer_id => break Some(i),
Some(_) => continue,
None => break None,
}
}
};
match off {
Some(i) => addr_infos[i].addrs.append(&mut new_a.addrs),
None => addr_infos.push(new_a),
}
}
Ok(addr_infos)
}
pub fn from_p2p_multiaddr(addr: Multiaddr) -> Result<AddrInfo> {
let mut comps = addr.split()?;
let peer_id = match comps.pop() {
Some(Multiaddr::P2p(val, _)) => val.to_peer_id(),
Some(Multiaddr::Ipfs(val, _)) => val.to_peer_id(),
_ => err_at!(Invalid, msg: format!("not p2p address"))?,
};
let addr_info = AddrInfo {
peer_id,
addrs: vec![Multiaddr::join(comps)?],
};
Ok(addr_info)
}
pub fn to_p2p_multiaddrs(&self) -> Result<Vec<Multiaddr>> {
let p2p_addr = {
let val = multiaddr::p2p::P2p::new(self.peer_id.clone());
Multiaddr::P2p(val, Box::new(Multiaddr::None))
};
let mut addrs = vec![];
for addr in self.addrs.clone().into_iter() {
let mut comps = addr.split()?;
comps.push(p2p_addr.clone());
addrs.push(Multiaddr::join(comps)?);
}
Ok(addrs)
}
pub fn to_peer_id(&self) -> PeerId {
self.peer_id.clone()
}
pub fn to_multiaddrs(&self) -> Vec<Multiaddr> {
self.addrs.clone()
}
}