mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-28 10:11:19 +00:00
Simplify the implementation of peer_info (#327)
* Simplify the implementation of peer_info * Add Serde-Support to MultiAddr
This commit is contained in:
parent
6c7ae04349
commit
7aa08917ea
@ -13,6 +13,9 @@ bs58 = "0.2.0"
|
||||
byteorder = "~0.4"
|
||||
multihash = { path = "../multihash" }
|
||||
integer-encoding = "~1.0.3"
|
||||
serde = "1.0.70"
|
||||
|
||||
[dev-dependencies]
|
||||
data-encoding = "~1.1.2"
|
||||
serde_json = "1.0"
|
||||
bincode = "1.0.1"
|
@ -6,6 +6,7 @@
|
||||
extern crate bs58;
|
||||
extern crate byteorder;
|
||||
extern crate integer_encoding;
|
||||
extern crate serde;
|
||||
pub extern crate multihash;
|
||||
|
||||
mod protocol;
|
||||
@ -14,7 +15,10 @@ mod errors;
|
||||
pub use errors::{Result, Error};
|
||||
pub use protocol::{Protocol, ProtocolArgSize, AddrComponent};
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeserializerError};
|
||||
|
||||
use std::fmt;
|
||||
use std::result::Result as StdResult;
|
||||
use std::iter::FromIterator;
|
||||
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6, IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::str::FromStr;
|
||||
@ -25,6 +29,35 @@ pub struct Multiaddr {
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Serialize for Multiaddr {
|
||||
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
// Serialize to a human-readable string "2015-05-15T17:01:00Z".
|
||||
self.to_string().serialize(serializer)
|
||||
} else {
|
||||
self.to_bytes().serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Multiaddr {
|
||||
fn deserialize<D>(deserializer: D) -> StdResult<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
let addr: String = Deserialize::deserialize(deserializer)?;
|
||||
addr.parse::<Multiaddr>().map_err(|err| DeserializerError::custom(err))
|
||||
} else {
|
||||
let addr: Vec<u8> = Deserialize::deserialize(deserializer)?;
|
||||
Multiaddr::from_bytes(addr).map_err(|err| DeserializerError::custom(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Multiaddr {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -1,5 +1,7 @@
|
||||
extern crate multiaddr;
|
||||
extern crate data_encoding;
|
||||
extern crate serde_json;
|
||||
extern crate bincode;
|
||||
|
||||
use data_encoding::hex;
|
||||
use multiaddr::*;
|
||||
@ -173,3 +175,24 @@ fn from_bytes_fail() {
|
||||
let bytes = vec![1, 2, 3, 4];
|
||||
assert!(Multiaddr::from_bytes(bytes).is_err());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn ser_and_deser_json() {
|
||||
let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
|
||||
let serialized = serde_json::to_string(&addr).unwrap();
|
||||
assert_eq!(serialized, "\"/ip4/0.0.0.0/tcp/0\"");
|
||||
let deserialized: Multiaddr = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(addr, deserialized);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn ser_and_deser_bincode() {
|
||||
let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>().unwrap();
|
||||
let serialized = bincode::serialize(&addr).unwrap();
|
||||
// compact addressing
|
||||
assert_eq!(serialized, vec![8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0]);
|
||||
let deserialized: Multiaddr = bincode::deserialize(&serialized).unwrap();
|
||||
assert_eq!(addr, deserialized);
|
||||
}
|
@ -11,8 +11,8 @@ futures = "0.1.0"
|
||||
owning_ref = "0.3.3"
|
||||
libp2p-core = { path = "../core" }
|
||||
multiaddr = { path = "../multiaddr" }
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde = "1.0.70"
|
||||
serde_derive = "1.0.70"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "2.2"
|
||||
|
@ -27,15 +27,12 @@
|
||||
//! more thoughts about this.
|
||||
|
||||
use multiaddr::Multiaddr;
|
||||
use serde::de::Error as DeserializerError;
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::cmp::Ordering;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use std::time::SystemTime;
|
||||
use TTL;
|
||||
|
||||
/// Information about a peer.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct PeerInfo {
|
||||
// Adresses, and the time at which they will be considered expired.
|
||||
addrs: Vec<(Multiaddr, SystemTime)>,
|
||||
@ -108,67 +105,6 @@ pub enum AddAddrBehaviour {
|
||||
IgnoreTtlIfInferior,
|
||||
}
|
||||
|
||||
impl Serialize for PeerInfo {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_struct("PeerInfo", 2)?;
|
||||
s.serialize_field(
|
||||
"addrs",
|
||||
&self.addrs
|
||||
.iter()
|
||||
.map(|&(ref addr, ref expires)| {
|
||||
let addr = addr.to_string();
|
||||
let from_epoch = expires.duration_since(UNIX_EPOCH)
|
||||
// This `unwrap_or` case happens if the user has their system time set to
|
||||
// before EPOCH. Times-to-live will be be longer than expected, but it's a very
|
||||
// improbable corner case and is not attackable in any way, so we don't really
|
||||
// care.
|
||||
.unwrap_or(Duration::new(0, 0));
|
||||
let secs = from_epoch
|
||||
.as_secs()
|
||||
.saturating_mul(1_000)
|
||||
.saturating_add(from_epoch.subsec_nanos() as u64 / 1_000_000);
|
||||
(addr, secs)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for PeerInfo {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// We deserialize to an intermdiate struct first, then turn that struct into a `PeerInfo`.
|
||||
let interm = {
|
||||
#[derive(Deserialize)]
|
||||
struct Interm {
|
||||
addrs: Vec<(String, u64)>,
|
||||
}
|
||||
Interm::deserialize(deserializer)?
|
||||
};
|
||||
|
||||
let addrs = {
|
||||
let mut out = Vec::with_capacity(interm.addrs.len());
|
||||
for (addr, since_epoch) in interm.addrs {
|
||||
let addr = match addr.parse::<Multiaddr>() {
|
||||
Ok(a) => a,
|
||||
Err(err) => return Err(DeserializerError::custom(err)),
|
||||
};
|
||||
let expires = UNIX_EPOCH + Duration::from_millis(since_epoch);
|
||||
out.push((addr, expires));
|
||||
}
|
||||
out
|
||||
};
|
||||
|
||||
Ok(PeerInfo { addrs: addrs })
|
||||
}
|
||||
}
|
||||
|
||||
// The reason why we need to implement the PartialOrd trait is that the datastore library (a
|
||||
// key-value storage) which we use allows performing queries where the results can be ordered.
|
||||
//
|
||||
@ -181,10 +117,12 @@ impl PartialOrd for PeerInfo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate serde_json;
|
||||
use super::*;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
#[test]
|
||||
fn ser_and_deser() {
|
||||
@ -198,4 +136,4 @@ mod tests {
|
||||
let deserialized: PeerInfo = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(peer_info, deserialized);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user