Make Multiaddr::iter borrow data (#478)

* Use `unsigned-varint` crate.

* Implement `Display` for `Protocol`.

Gives `ToString` for free.

* Use `Cow` in `AddrComponent`.

* Add `AddrComponent::acquire`.

* Document `AddrComponent::acquire`.
This commit is contained in:
Toralf Wittner 2018-09-14 10:21:14 +02:00 committed by GitHub
parent 5980a4538e
commit b2756c8fa9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 169 additions and 140 deletions

View File

@ -12,8 +12,8 @@ version = "0.3.0"
bs58 = "0.2.0" bs58 = "0.2.0"
byteorder = "~0.4" byteorder = "~0.4"
multihash = { path = "../multihash" } multihash = { path = "../multihash" }
integer-encoding = "~1.0.3"
serde = "1.0.70" serde = "1.0.70"
unsigned-varint = "0.1"
[dev-dependencies] [dev-dependencies]
data-encoding = "~1.1.2" data-encoding = "~1.1.2"

View File

@ -1,7 +1,8 @@
use std::{net, fmt, error, io, num, string}; use std::{net, fmt, error, io, num, str, string};
use bs58; use bs58;
use multihash; use multihash;
use byteorder; use byteorder;
use unsigned_varint::decode;
pub type Result<T> = ::std::result::Result<T, Error>; pub type Result<T> = ::std::result::Result<T, Error>;
@ -13,30 +14,29 @@ pub enum Error {
InvalidMultiaddr, InvalidMultiaddr,
MissingAddress, MissingAddress,
ParsingError(Box<error::Error + Send + Sync>), ParsingError(Box<error::Error + Send + Sync>),
InvalidUvar(decode::Error)
} }
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(error::Error::description(self)) match self {
Error::UnknownProtocol => f.write_str("unknown protocol"),
Error::UnknownProtocolString => f.write_str("unknown protocol string"),
Error::InvalidMultiaddr => f.write_str("invalid multiaddr"),
Error::MissingAddress => f.write_str("protocol requires address, none given"),
Error::ParsingError(e) => write!(f, "failed to parse: {}", e),
Error::InvalidUvar(e) => write!(f, "failed to decode unsigned varint: {}", e)
}
} }
} }
impl error::Error for Error { impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::UnknownProtocol => "unknown protocol",
Error::UnknownProtocolString => "unknown protocol string",
Error::InvalidMultiaddr => "invalid multiaddr",
Error::MissingAddress => "protocol requires address, none given",
Error::ParsingError(_) => "failed to parse",
}
}
#[inline] #[inline]
fn cause(&self) -> Option<&error::Error> { fn cause(&self) -> Option<&dyn error::Error> {
match *self { if let Error::ParsingError(e) = self {
Error::ParsingError(ref err) => Some(&**err), Some(&**e)
_ => None } else {
None
} }
} }
} }
@ -59,7 +59,6 @@ impl From<bs58::decode::DecodeError> for Error {
} }
} }
impl From<net::AddrParseError> for Error { impl From<net::AddrParseError> for Error {
fn from(err: net::AddrParseError) -> Error { fn from(err: net::AddrParseError) -> Error {
Error::ParsingError(err.into()) Error::ParsingError(err.into())
@ -83,3 +82,16 @@ impl From<string::FromUtf8Error> for Error {
Error::ParsingError(err.into()) Error::ParsingError(err.into())
} }
} }
impl From<str::Utf8Error> for Error {
fn from(err: str::Utf8Error) -> Error {
Error::ParsingError(err.into())
}
}
impl From<decode::Error> for Error {
fn from(e: decode::Error) -> Error {
Error::InvalidUvar(e)
}
}

View File

@ -5,8 +5,8 @@
extern crate bs58; extern crate bs58;
extern crate byteorder; extern crate byteorder;
extern crate integer_encoding;
extern crate serde; extern crate serde;
extern crate unsigned_varint;
pub extern crate multihash; pub extern crate multihash;
mod protocol; mod protocol;
@ -266,16 +266,16 @@ impl Multiaddr {
/// assert_eq!(address.pop().unwrap(), AddrComponent::UDT); /// assert_eq!(address.pop().unwrap(), AddrComponent::UDT);
/// ``` /// ```
/// ///
pub fn pop(&mut self) -> Option<AddrComponent> { pub fn pop<'a>(&mut self) -> Option<AddrComponent<'a>> {
// Note: could be more optimized // Note: could be more optimized
let mut list = self.iter().collect::<Vec<_>>(); let mut list = self.iter().map(AddrComponent::acquire).collect::<Vec<_>>();
let last_elem = list.pop(); let last_elem = list.pop();
*self = list.into_iter().collect(); *self = list.into_iter().collect();
last_elem last_elem
} }
} }
impl From<AddrComponent> for Multiaddr { impl<'a> From<AddrComponent<'a>> for Multiaddr {
fn from(addr: AddrComponent) -> Multiaddr { fn from(addr: AddrComponent) -> Multiaddr {
let mut out = Vec::new(); let mut out = Vec::new();
addr.write_bytes(&mut out).expect( addr.write_bytes(&mut out).expect(
@ -286,7 +286,7 @@ impl From<AddrComponent> for Multiaddr {
} }
impl<'a> IntoIterator for &'a Multiaddr { impl<'a> IntoIterator for &'a Multiaddr {
type Item = AddrComponent; type Item = AddrComponent<'a>;
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
#[inline] #[inline]
@ -295,10 +295,10 @@ impl<'a> IntoIterator for &'a Multiaddr {
} }
} }
impl FromIterator<AddrComponent> for Multiaddr { impl<'a> FromIterator<AddrComponent<'a>> for Multiaddr {
fn from_iter<T>(iter: T) -> Self fn from_iter<T>(iter: T) -> Self
where where
T: IntoIterator<Item = AddrComponent>, T: IntoIterator<Item = AddrComponent<'a>>,
{ {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for cmp in iter { for cmp in iter {
@ -348,9 +348,9 @@ impl FromStr for Multiaddr {
pub struct Iter<'a>(&'a [u8]); pub struct Iter<'a>(&'a [u8]);
impl<'a> Iterator for Iter<'a> { impl<'a> Iterator for Iter<'a> {
type Item = AddrComponent; type Item = AddrComponent<'a>;
fn next(&mut self) -> Option<AddrComponent> { fn next(&mut self) -> Option<Self::Item> {
if self.0.is_empty() { if self.0.is_empty() {
return None; return None;
} }

View File

@ -1,12 +1,15 @@
use bs58; use bs58;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
use std::convert::From;
use std::io::{Cursor, Write, Result as IoResult};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::{
borrow::Cow,
convert::From,
fmt,
io::{Cursor, Write, Result as IoResult},
net::{Ipv4Addr, Ipv6Addr},
str::{self, FromStr}
};
use multihash::Multihash; use multihash::Multihash;
use integer_encoding::{VarInt, VarIntWriter}; use unsigned_varint::{encode, decode};
use {Result, Error}; use {Result, Error};
///! # Protocol ///! # Protocol
@ -55,33 +58,33 @@ impl From<Protocol> for u64 {
} }
} }
impl ToString for Protocol { impl fmt::Display for Protocol {
fn to_string(&self) -> String { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match self {
Protocol::IP4 => "ip4", Protocol::IP4 => f.write_str("ip4"),
Protocol::TCP => "tcp", Protocol::TCP => f.write_str("tcp"),
Protocol::UDP => "udp", Protocol::UDP => f.write_str("udp"),
Protocol::DCCP => "dccp", Protocol::DCCP => f.write_str("dccp"),
Protocol::IP6 => "ip6", Protocol::IP6 => f.write_str("ip6"),
Protocol::DNS4 => "dns4", Protocol::DNS4 => f.write_str("dns4"),
Protocol::DNS6 => "dns6", Protocol::DNS6 => f.write_str("dns6"),
Protocol::SCTP => "sctp", Protocol::SCTP => f.write_str("sctp"),
Protocol::UDT => "udt", Protocol::UDT => f.write_str("udt"),
Protocol::UTP => "utp", Protocol::UTP => f.write_str("utp"),
Protocol::UNIX => "unix", Protocol::UNIX => f.write_str("unix"),
Protocol::P2P => "p2p", Protocol::P2P => f.write_str("p2p"),
Protocol::HTTP => "http", Protocol::HTTP => f.write_str("http"),
Protocol::HTTPS => "https", Protocol::HTTPS => f.write_str("https"),
Protocol::ONION => "onion", Protocol::ONION => f.write_str("onion"),
Protocol::QUIC => "quic", Protocol::QUIC => f.write_str("quic"),
Protocol::WS => "ws", Protocol::WS => f.write_str("ws"),
Protocol::WSS => "wss", Protocol::WSS => f.write_str("wss"),
Protocol::Libp2pWebsocketStar => "p2p-websocket-star", Protocol::Libp2pWebsocketStar => f.write_str("p2p-websocket-star"),
Protocol::Libp2pWebrtcStar => "p2p-webrtc-star", Protocol::Libp2pWebrtcStar => f.write_str("p2p-webrtc-star"),
Protocol::Libp2pWebrtcDirect => "p2p-webrtc-direct", Protocol::Libp2pWebrtcDirect => f.write_str("p2p-webrtc-direct"),
Protocol::P2pCircuit => "p2p-circuit", Protocol::P2pCircuit => f.write_str("p2p-circuit"),
Protocol::Memory => "memory", Protocol::Memory => f.write_str("memory"),
}.to_owned() }
} }
} }
@ -223,7 +226,7 @@ impl Protocol {
/// AddrComponent::IP4(Ipv4Addr::new(127, 0, 0, 1))); /// AddrComponent::IP4(Ipv4Addr::new(127, 0, 0, 1)));
/// ``` /// ```
/// ///
pub fn parse_data(&self, a: &str) -> Result<AddrComponent> { pub fn parse_data<'a>(&self, a: &'a str) -> Result<AddrComponent<'a>> {
match *self { match *self {
Protocol::IP4 => { Protocol::IP4 => {
let addr = Ipv4Addr::from_str(a)?; let addr = Ipv4Addr::from_str(a)?;
@ -233,12 +236,8 @@ impl Protocol {
let addr = Ipv6Addr::from_str(a)?; let addr = Ipv6Addr::from_str(a)?;
Ok(AddrComponent::IP6(addr)) Ok(AddrComponent::IP6(addr))
} }
Protocol::DNS4 => { Protocol::DNS4 => Ok(AddrComponent::DNS4(Cow::Borrowed(a))),
Ok(AddrComponent::DNS4(a.to_owned())) Protocol::DNS6 => Ok(AddrComponent::DNS6(Cow::Borrowed(a))),
}
Protocol::DNS6 => {
Ok(AddrComponent::DNS6(a.to_owned()))
}
Protocol::TCP => { Protocol::TCP => {
let parsed: u16 = a.parse()?; let parsed: u16 = a.parse()?;
Ok(AddrComponent::TCP(parsed)) Ok(AddrComponent::TCP(parsed))
@ -262,9 +261,7 @@ impl Protocol {
Protocol::ONION => unimplemented!(), // TODO: Protocol::ONION => unimplemented!(), // TODO:
Protocol::QUIC => Ok(AddrComponent::QUIC), Protocol::QUIC => Ok(AddrComponent::QUIC),
Protocol::UTP => Ok(AddrComponent::UTP), Protocol::UTP => Ok(AddrComponent::UTP),
Protocol::UNIX => { Protocol::UNIX => Ok(AddrComponent::UNIX(Cow::Borrowed(a))),
Ok(AddrComponent::UNIX(a.to_owned()))
}
Protocol::UDT => Ok(AddrComponent::UDT), Protocol::UDT => Ok(AddrComponent::UDT),
Protocol::HTTP => Ok(AddrComponent::HTTP), Protocol::HTTP => Ok(AddrComponent::HTTP),
Protocol::HTTPS => Ok(AddrComponent::HTTPS), Protocol::HTTPS => Ok(AddrComponent::HTTPS),
@ -280,22 +277,22 @@ impl Protocol {
} }
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub enum AddrComponent { pub enum AddrComponent<'a> {
IP4(Ipv4Addr), IP4(Ipv4Addr),
TCP(u16), TCP(u16),
UDP(u16), UDP(u16),
DCCP(u16), DCCP(u16),
IP6(Ipv6Addr), IP6(Ipv6Addr),
DNS4(String), DNS4(Cow<'a, str>),
DNS6(String), DNS6(Cow<'a, str>),
SCTP(u16), SCTP(u16),
UDT, UDT,
UTP, UTP,
UNIX(String), UNIX(Cow<'a, str>),
P2P(Multihash), P2P(Multihash),
HTTP, HTTP,
HTTPS, HTTPS,
ONION(Vec<u8>), ONION(Cow<'a, [u8]>),
QUIC, QUIC,
WS, WS,
WSS, WSS,
@ -306,7 +303,37 @@ pub enum AddrComponent {
Memory, Memory,
} }
impl AddrComponent { impl<'a> AddrComponent<'a> {
/// Turn this `AddrComponent` into one that owns its data, thus being valid for any lifetime.
pub fn acquire<'b>(self) -> AddrComponent<'b> {
use AddrComponent::*;
match self {
DNS4(cow) => DNS4(Cow::Owned(cow.into_owned())),
DNS6(cow) => DNS6(Cow::Owned(cow.into_owned())),
UNIX(cow) => UNIX(Cow::Owned(cow.into_owned())),
ONION(cow) => ONION(Cow::Owned(cow.into_owned())),
IP4(a) => IP4(a),
TCP(a) => TCP(a),
UDP(a) => UDP(a),
DCCP(a) => DCCP(a),
IP6(a) => IP6(a),
SCTP(a) => SCTP(a),
UDT => UDT,
UTP => UTP,
P2P(a) => P2P(a),
HTTP => HTTP,
HTTPS => HTTPS,
QUIC => QUIC,
WS => WS,
WSS => WSS,
Libp2pWebsocketStar => Libp2pWebsocketStar,
Libp2pWebrtcStar => Libp2pWebrtcStar,
Libp2pWebrtcDirect => Libp2pWebrtcDirect,
P2pCircuit => P2pCircuit,
Memory => Memory
}
}
/// Returns the `Protocol` corresponding to this `AddrComponent`. /// Returns the `Protocol` corresponding to this `AddrComponent`.
#[inline] #[inline]
pub fn protocol_id(&self) -> Protocol { pub fn protocol_id(&self) -> Protocol {
@ -340,20 +367,13 @@ impl AddrComponent {
/// Builds an `AddrComponent` from an array that starts with a bytes representation. On /// Builds an `AddrComponent` from an array that starts with a bytes representation. On
/// success, also returns the rest of the slice. /// success, also returns the rest of the slice.
pub fn from_bytes(input: &[u8]) -> Result<(AddrComponent, &[u8])> { pub fn from_bytes(input: &[u8]) -> Result<(AddrComponent, &[u8])> {
let (proto_num, proto_id_len) = u64::decode_var(input); // TODO: will panic if ID too large let (proto_num, input) = decode::u64(input)?;
let protocol_id = Protocol::from(proto_num)?; let protocol_id = Protocol::from(proto_num)?;
let (data_offset, data_size) = match protocol_id.size() { let (data_size, input) = match protocol_id.size() {
ProtocolArgSize::Fixed { bytes } => { ProtocolArgSize::Fixed { bytes } => (bytes, input),
(0, bytes) ProtocolArgSize::Variable => decode::usize(input)?
},
ProtocolArgSize::Variable => {
let (data_size, varint_len) = u64::decode_var(&input[proto_id_len..]); // TODO: will panic if ID too large
(varint_len, data_size as usize)
},
}; };
let (data, rest) = input.split_at(data_size);
let (data, rest) = input[proto_id_len..][data_offset..].split_at(data_size);
let addr_component = match protocol_id { let addr_component = match protocol_id {
Protocol::IP4 => { Protocol::IP4 => {
@ -361,10 +381,10 @@ impl AddrComponent {
}, },
Protocol::IP6 => { Protocol::IP6 => {
let mut rdr = Cursor::new(data); let mut rdr = Cursor::new(data);
let mut seg = vec![]; let mut seg = [0; 8];
for _ in 0..8 { for i in 0..8 {
seg.push(rdr.read_u16::<BigEndian>()?); seg[i] = rdr.read_u16::<BigEndian>()?;
} }
let addr = Ipv6Addr::new(seg[0], let addr = Ipv6Addr::new(seg[0],
@ -378,10 +398,10 @@ impl AddrComponent {
AddrComponent::IP6(addr) AddrComponent::IP6(addr)
} }
Protocol::DNS4 => { Protocol::DNS4 => {
AddrComponent::DNS4(String::from_utf8(data.to_owned())?) AddrComponent::DNS4(Cow::Borrowed(str::from_utf8(data)?))
} }
Protocol::DNS6 => { Protocol::DNS6 => {
AddrComponent::DNS6(String::from_utf8(data.to_owned())?) AddrComponent::DNS6(Cow::Borrowed(str::from_utf8(data)?))
} }
Protocol::TCP => { Protocol::TCP => {
let mut rdr = Cursor::new(data); let mut rdr = Cursor::new(data);
@ -404,7 +424,7 @@ impl AddrComponent {
AddrComponent::SCTP(num) AddrComponent::SCTP(num)
} }
Protocol::UNIX => { Protocol::UNIX => {
AddrComponent::UNIX(String::from_utf8(data.to_owned())?) AddrComponent::UNIX(Cow::Borrowed(str::from_utf8(data)?))
} }
Protocol::P2P => { Protocol::P2P => {
AddrComponent::P2P(Multihash::from_bytes(data.to_owned())?) AddrComponent::P2P(Multihash::from_bytes(data.to_owned())?)
@ -429,7 +449,7 @@ impl AddrComponent {
/// Turns this address component into bytes by writing it to a `Write`. /// Turns this address component into bytes by writing it to a `Write`.
pub fn write_bytes<W: Write>(self, out: &mut W) -> IoResult<()> { pub fn write_bytes<W: Write>(self, out: &mut W) -> IoResult<()> {
out.write_varint(Into::<u64>::into(self.protocol_id()))?; out.write_all(encode::u64(self.protocol_id().into(), &mut encode::u64_buffer()))?;
match self { match self {
AddrComponent::IP4(addr) => { AddrComponent::IP4(addr) => {
@ -446,12 +466,12 @@ impl AddrComponent {
} }
AddrComponent::DNS4(s) | AddrComponent::DNS6(s) | AddrComponent::UNIX(s) => { AddrComponent::DNS4(s) | AddrComponent::DNS6(s) | AddrComponent::UNIX(s) => {
let bytes = s.as_bytes(); let bytes = s.as_bytes();
out.write_varint(bytes.len())?; out.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
out.write_all(&bytes)?; out.write_all(&bytes)?;
} }
AddrComponent::P2P(multihash) => { AddrComponent::P2P(multihash) => {
let bytes = multihash.into_bytes(); let bytes = multihash.into_bytes();
out.write_varint(bytes.len())?; out.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
out.write_all(&bytes)?; out.write_all(&bytes)?;
} }
AddrComponent::ONION(_) => { AddrComponent::ONION(_) => {
@ -475,46 +495,46 @@ impl AddrComponent {
} }
} }
impl ToString for AddrComponent { impl<'a> fmt::Display for AddrComponent<'a> {
fn to_string(&self) -> String { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match self {
AddrComponent::IP4(ref addr) => format!("/ip4/{}", addr), AddrComponent::IP4(addr) => write!(f, "/ip4/{}", addr),
AddrComponent::TCP(port) => format!("/tcp/{}", port), AddrComponent::TCP(port) => write!(f, "/tcp/{}", port),
AddrComponent::UDP(port) => format!("/udp/{}", port), AddrComponent::UDP(port) => write!(f, "/udp/{}", port),
AddrComponent::DCCP(port) => format!("/dccp/{}", port), AddrComponent::DCCP(port) => write!(f, "/dccp/{}", port),
AddrComponent::IP6(ref addr) => format!("/ip6/{}", addr), AddrComponent::IP6(addr) => write!(f, "/ip6/{}", addr),
AddrComponent::DNS4(ref s) => format!("/dns4/{}", s.clone()), AddrComponent::DNS4(s) => write!(f, "/dns4/{}", s),
AddrComponent::DNS6(ref s) => format!("/dns6/{}", s.clone()), AddrComponent::DNS6(s) => write!(f, "/dns6/{}", s),
AddrComponent::SCTP(port) => format!("/sctp/{}", port), AddrComponent::SCTP(port) => write!(f, "/sctp/{}", port),
AddrComponent::UDT => format!("/udt"), AddrComponent::UDT => f.write_str("/udt"),
AddrComponent::UTP => format!("/utp"), AddrComponent::UTP => f.write_str("/utp"),
AddrComponent::UNIX(ref s) => format!("/unix/{}", s.clone()), AddrComponent::UNIX(s) => write!(f, "/unix/{}", s),
AddrComponent::P2P(ref c) => format!("/p2p/{}", bs58::encode(c.as_bytes()).into_string()), AddrComponent::P2P(c) => write!(f, "/p2p/{}", bs58::encode(c.as_bytes()).into_string()),
AddrComponent::HTTP => format!("/http"), AddrComponent::HTTP => f.write_str("/http"),
AddrComponent::HTTPS => format!("/https"), AddrComponent::HTTPS => f.write_str("/https"),
AddrComponent::ONION(_) => unimplemented!(),//format!("/onion"), // TODO: AddrComponent::ONION(_) => unimplemented!(),//write!("/onion"), // TODO:
AddrComponent::QUIC => format!("/quic"), AddrComponent::QUIC => f.write_str("/quic"),
AddrComponent::WS => format!("/ws"), AddrComponent::WS => f.write_str("/ws"),
AddrComponent::WSS => format!("/wss"), AddrComponent::WSS => f.write_str("/wss"),
AddrComponent::Libp2pWebsocketStar => format!("/p2p-websocket-star"), AddrComponent::Libp2pWebsocketStar => f.write_str("/p2p-websocket-star"),
AddrComponent::Libp2pWebrtcStar => format!("/p2p-webrtc-star"), AddrComponent::Libp2pWebrtcStar => f.write_str("/p2p-webrtc-star"),
AddrComponent::Libp2pWebrtcDirect => format!("/p2p-webrtc-direct"), AddrComponent::Libp2pWebrtcDirect => f.write_str("/p2p-webrtc-direct"),
AddrComponent::P2pCircuit => format!("/p2p-circuit"), AddrComponent::P2pCircuit => f.write_str("/p2p-circuit"),
AddrComponent::Memory => format!("/memory"), AddrComponent::Memory => f.write_str("/memory"),
} }
} }
} }
impl From<Ipv4Addr> for AddrComponent { impl<'a> From<Ipv4Addr> for AddrComponent<'a> {
#[inline] #[inline]
fn from(addr: Ipv4Addr) -> AddrComponent { fn from(addr: Ipv4Addr) -> Self {
AddrComponent::IP4(addr) AddrComponent::IP4(addr)
} }
} }
impl From<Ipv6Addr> for AddrComponent { impl<'a> From<Ipv6Addr> for AddrComponent<'a> {
#[inline] #[inline]
fn from(addr: Ipv6Addr) -> AddrComponent { fn from(addr: Ipv6Addr) -> Self {
AddrComponent::IP6(addr) AddrComponent::IP6(addr)
} }
} }

View File

@ -284,13 +284,11 @@ pub struct PeerIdTransportOutput<S> {
// If the multiaddress is in the form `/p2p/...`, turn it into a `PeerId`. // If the multiaddress is in the form `/p2p/...`, turn it into a `PeerId`.
// Otherwise, return it as-is. // Otherwise, return it as-is.
fn multiaddr_to_peerid(addr: Multiaddr) -> Result<PeerId, Multiaddr> { fn multiaddr_to_peerid(addr: Multiaddr) -> Result<PeerId, Multiaddr> {
let components = addr.iter().collect::<Vec<_>>(); if addr.iter().next().is_none() {
if components.len() < 1 { return Err(addr)
return Err(addr);
} }
match addr.iter().last() {
match components.last() { Some(AddrComponent::P2P(ref peer_id)) => {
Some(&AddrComponent::P2P(ref peer_id)) => {
match PeerId::from_multihash(peer_id.clone()) { match PeerId::from_multihash(peer_id.clone()) {
Ok(peer_id) => Ok(peer_id), Ok(peer_id) => Ok(peer_id),
Err(_) => Err(addr), Err(_) => Err(addr),

View File

@ -149,7 +149,7 @@ where
AddrComponent::DNS6(ref name) => { AddrComponent::DNS6(ref name) => {
future::Either::A(resolve_dns(name, &resolver, ResolveTy::Dns6)) future::Either::A(resolve_dns(name, &resolver, ResolveTy::Dns6))
} }
cmp => future::Either::B(future::ok(cmp)), cmp => future::Either::B(future::ok(cmp.acquire())),
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter(); .into_iter();
@ -188,11 +188,11 @@ enum ResolveTy {
} }
// Resolve a DNS name and returns a future with the result. // Resolve a DNS name and returns a future with the result.
fn resolve_dns( fn resolve_dns<'a>(
name: &str, name: &str,
resolver: &CpuPoolResolver, resolver: &CpuPoolResolver,
ty: ResolveTy, ty: ResolveTy,
) -> impl Future<Item = AddrComponent, Error = IoError> { ) -> impl Future<Item = AddrComponent<'a>, Error = IoError> {
let debug_name = if log_enabled!(Level::Trace) { let debug_name = if log_enabled!(Level::Trace) {
Some(name.to_owned()) Some(name.to_owned())
} else { } else {

View File

@ -148,7 +148,7 @@ fn multiaddr_to_path(addr: &Multiaddr) -> Result<PathBuf, ()> {
} }
match path { match path {
Some(AddrComponent::UNIX(ref path)) => Ok(path.into()), Some(AddrComponent::UNIX(ref path)) => Ok(path.as_ref().into()),
_ => Err(()) _ => Err(())
} }
} }
@ -159,8 +159,7 @@ mod tests {
use futures::stream::Stream; use futures::stream::Stream;
use futures::Future; use futures::Future;
use multiaddr::{AddrComponent, Multiaddr}; use multiaddr::{AddrComponent, Multiaddr};
use std; use std::{self, borrow::Cow, path::Path};
use std::path::Path;
use libp2p_core::Transport; use libp2p_core::Transport;
use tempfile; use tempfile;
use tokio_current_thread; use tokio_current_thread;
@ -189,7 +188,7 @@ mod tests {
let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = tempfile::tempdir().unwrap();
let socket = temp_dir.path().join("socket"); let socket = temp_dir.path().join("socket");
let addr = Multiaddr::from(AddrComponent::UNIX(socket.to_string_lossy().into_owned())); let addr = Multiaddr::from(AddrComponent::UNIX(Cow::Owned(socket.to_string_lossy().into_owned())));
let addr2 = addr.clone(); let addr2 = addr.clone();
std::thread::spawn(move || { std::thread::spawn(move || {