use std::{
convert::{TryFrom, TryInto},
time,
};
use crate::{
addr_info::AddrInfo,
multiaddr::Multiaddr,
multicodec::{self, Multicodec},
pb::peer_record_proto,
peer_id::PeerId,
Error, Result,
};
pub const MULTICODEC: u128 = multicodec::LIBP2P_PEER_RECORD;
#[derive(Clone, Eq, PartialEq)]
pub struct PeerRecord {
peer_id: PeerId,
addrs: Vec<Multiaddr>,
seq: u128,
}
impl TryFrom<AddrInfo> for PeerRecord {
type Error = Error;
fn try_from(val: AddrInfo) -> Result<Self> {
let dur = {
let now = time::SystemTime::now();
err_at!(Fatal, now.duration_since(time::UNIX_EPOCH))?
};
let val = PeerRecord {
peer_id: val.to_peer_id(),
addrs: val.to_multiaddrs(),
seq: dur.as_nanos(),
};
Ok(val)
}
}
impl TryFrom<peer_record_proto::PeerRecord> for PeerRecord {
type Error = Error;
fn try_from(val: peer_record_proto::PeerRecord) -> Result<Self> {
let mut addrs = vec![];
for addr in val.addresses.iter() {
let (ma, _) = Multiaddr::decode(&addr.multiaddr)?;
addrs.push(ma)
}
let (peer_id, _) = PeerId::decode(&val.peer_id)?;
let rec = PeerRecord {
peer_id,
addrs,
seq: val.seq.into(),
};
Ok(rec)
}
}
impl TryFrom<PeerRecord> for peer_record_proto::PeerRecord {
type Error = Error;
fn try_from(val: PeerRecord) -> Result<Self> {
let mut addresses = vec![];
for addr in val.addrs.into_iter() {
let address = peer_record_proto::peer_record::AddressInfo {
multiaddr: addr.encode()?,
};
addresses.push(address);
}
let pr = peer_record_proto::PeerRecord {
peer_id: val.peer_id.encode()?,
seq: val.seq as u64,
addresses,
};
Ok(pr)
}
}
impl PeerRecord {
pub fn from_peer_id(peer_id: PeerId, addrs: Vec<Multiaddr>) -> Result<PeerRecord> {
let dur = {
let now = time::SystemTime::now();
err_at!(Fatal, now.duration_since(time::UNIX_EPOCH))?
};
let val = PeerRecord {
peer_id,
addrs,
seq: dur.as_nanos(),
};
Ok(val)
}
pub fn decode_protobuf(data: &[u8]) -> Result<Self> {
use prost::Message;
let pr = {
let res = peer_record_proto::PeerRecord::decode(data);
err_at!(DecodeError, res)?
};
Ok(pr.try_into()?)
}
pub fn encode_protobuf(self) -> Result<Vec<u8>> {
use prost::Message;
let pr: peer_record_proto::PeerRecord = self.try_into()?;
let mut buf = Vec::with_capacity(pr.encoded_len());
err_at!(EncodeError, pr.encode(&mut buf))?;
Ok(buf)
}
pub fn to_domain(&self) -> String {
"libp2p-peer-record".to_string()
}
pub fn to_multicodec(&self) -> Multicodec {
multicodec::LIBP2P_PEER_RECORD.into()
}
}