multiaddr: Replace Bytes with Arc<Vec<u8>>. (#1370)

* multiaddr: Replace `Bytes` with `Arc<Vec<u8>>`.

* Annotate type of `io::Cursor`.

Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>

* Annotate type of `io::Cursor`.

Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
This commit is contained in:
Toralf Wittner
2020-01-07 13:06:16 +01:00
committed by Pierre Krieger
parent d83619109b
commit ab2eb7a51d
3 changed files with 27 additions and 52 deletions

View File

@ -12,11 +12,11 @@ version = "0.6.0"
arrayref = "0.3" arrayref = "0.3"
bs58 = "0.3.0" bs58 = "0.3.0"
byteorder = "1.3.1" byteorder = "1.3.1"
bytes = "0.4.12"
data-encoding = "2.1" data-encoding = "2.1"
multihash = { package = "parity-multihash", version = "0.2.0", path = "../multihash" } multihash = { package = "parity-multihash", version = "0.2.0", path = "../multihash" }
percent-encoding = "2.1.0" percent-encoding = "2.1.0"
serde = "1.0.70" serde = "1.0.70"
static_assertions = "1.1"
unsigned-varint = "0.3" unsigned-varint = "0.3"
url = { version = "2.1.0", default-features = false } url = { version = "2.1.0", default-features = false }

View File

@ -5,9 +5,7 @@ pub use multihash;
mod protocol; mod protocol;
mod errors; mod errors;
mod from_url; mod from_url;
mod util;
use bytes::Bytes;
use serde::{ use serde::{
Deserialize, Deserialize,
Deserializer, Deserializer,
@ -18,28 +16,36 @@ use serde::{
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
fmt, fmt,
io,
iter::FromIterator, iter::FromIterator,
net::{IpAddr, Ipv4Addr, Ipv6Addr}, net::{IpAddr, Ipv4Addr, Ipv6Addr},
result::Result as StdResult, result::Result as StdResult,
str::FromStr str::FromStr,
sync::Arc
}; };
pub use self::errors::{Result, Error}; pub use self::errors::{Result, Error};
pub use self::from_url::{FromUrlErr, from_url, from_url_lossy}; pub use self::from_url::{FromUrlErr, from_url, from_url_lossy};
pub use self::protocol::Protocol; pub use self::protocol::Protocol;
static_assertions::const_assert! {
// This check is most certainly overkill right now, but done here
// anyway to ensure the `as u64` casts in this crate are safe.
std::mem::size_of::<usize>() <= std::mem::size_of::<u64>()
}
/// Representation of a Multiaddr. /// Representation of a Multiaddr.
#[derive(PartialEq, Eq, Clone, Hash)] #[derive(PartialEq, Eq, Clone, Hash)]
pub struct Multiaddr { bytes: Bytes } pub struct Multiaddr { bytes: Arc<Vec<u8>> }
impl Multiaddr { impl Multiaddr {
/// Create a new, empty multiaddress. /// Create a new, empty multiaddress.
pub fn empty() -> Self { pub fn empty() -> Self {
Self { bytes: Bytes::new() } Self { bytes: Arc::new(Vec::new()) }
} }
/// Create a new, empty multiaddress with the given capacity. /// Create a new, empty multiaddress with the given capacity.
pub fn with_capacity(n: usize) -> Self { pub fn with_capacity(n: usize) -> Self {
Self { bytes: Bytes::with_capacity(n) } Self { bytes: Arc::new(Vec::with_capacity(n)) }
} }
/// Return the length in bytes of this multiaddress. /// Return the length in bytes of this multiaddress.
@ -65,9 +71,9 @@ impl Multiaddr {
/// ``` /// ```
/// ///
pub fn push(&mut self, p: Protocol<'_>) { pub fn push(&mut self, p: Protocol<'_>) {
let mut w = Vec::new(); let mut w = io::Cursor::<&mut Vec<u8>>::new(Arc::make_mut(&mut self.bytes));
p.write_bytes(&mut w).expect("Writing to a `Vec` never fails."); w.set_position(w.get_ref().len() as u64);
self.bytes.extend_from_slice(&w); p.write_bytes(&mut w).expect("Writing to a `io::Cursor<&mut Vec<u8>>` never fails.")
} }
/// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty. /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty.
@ -93,25 +99,16 @@ impl Multiaddr {
slice = s slice = s
}; };
let remaining_len = self.bytes.len() - slice.len(); let remaining_len = self.bytes.len() - slice.len();
self.bytes.truncate(remaining_len); Arc::make_mut(&mut self.bytes).truncate(remaining_len);
Some(protocol) Some(protocol)
} }
/// Like [`push`] but more efficient if this `Multiaddr` has no living clones. /// Like [`push`] but consumes `self`.
pub fn with(self, p: Protocol<'_>) -> Self { pub fn with(mut self, p: Protocol<'_>) -> Self {
match self.bytes.try_mut() { let mut w = io::Cursor::<&mut Vec<u8>>::new(Arc::make_mut(&mut self.bytes));
Ok(bytes) => { w.set_position(w.get_ref().len() as u64);
let mut w = util::BytesWriter(bytes); p.write_bytes(&mut w).expect("Writing to a `io::Cursor<&mut Vec<u8>>` never fails.");
p.write_bytes(&mut w).expect("Writing to a `BytesWriter` never fails."); self
Multiaddr { bytes: w.0.freeze() }
}
Err(mut bytes) => {
let mut w = Vec::new();
p.write_bytes(&mut w).expect("Writing to a `Vec` never fails.");
bytes.extend_from_slice(&w);
Multiaddr { bytes }
}
}
} }
/// Returns the components of this multiaddress. /// Returns the components of this multiaddress.
@ -217,7 +214,7 @@ impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
for cmp in iter { for cmp in iter {
cmp.write_bytes(&mut writer).expect("Writing to a `Vec` never fails."); cmp.write_bytes(&mut writer).expect("Writing to a `Vec` never fails.");
} }
Multiaddr { bytes: writer.into() } Multiaddr { bytes: Arc::new(writer) }
} }
} }
@ -238,7 +235,7 @@ impl FromStr for Multiaddr {
p.write_bytes(&mut writer).expect("Writing to a `Vec` never fails."); p.write_bytes(&mut writer).expect("Writing to a `Vec` never fails.");
} }
Ok(Multiaddr { bytes: writer.into() }) Ok(Multiaddr { bytes: Arc::new(writer) })
} }
} }
@ -265,7 +262,7 @@ impl<'a> From<Protocol<'a>> for Multiaddr {
fn from(p: Protocol<'a>) -> Multiaddr { fn from(p: Protocol<'a>) -> Multiaddr {
let mut w = Vec::new(); let mut w = Vec::new();
p.write_bytes(&mut w).expect("Writing to a `Vec` never fails."); p.write_bytes(&mut w).expect("Writing to a `Vec` never fails.");
Multiaddr { bytes: w.into() } Multiaddr { bytes: Arc::new(w) }
} }
} }
@ -300,7 +297,7 @@ impl TryFrom<Vec<u8>> for Multiaddr {
let (_, s) = Protocol::from_bytes(slice)?; let (_, s) = Protocol::from_bytes(slice)?;
slice = s slice = s
} }
Ok(Multiaddr { bytes: v.into() }) Ok(Multiaddr { bytes: Arc::new(v) })
} }
} }
@ -413,4 +410,3 @@ macro_rules! multiaddr {
} }
} }
} }

View File

@ -1,21 +0,0 @@
use bytes::BytesMut;
/// An [`io::Write`] impl for [`BytesMut`].
///
/// In contrast to [`bytes::buf::Writer`] this [`io::Write] implementation
/// transparently reserves enough space for [`io::Write::write_all`] to
/// succeed, i.e. it does not require upfront reservation of space.
pub(crate) struct BytesWriter(pub(crate) BytesMut);
impl std::io::Write for BytesWriter {
fn write(&mut self, src: &[u8]) -> std::io::Result<usize> {
self.0.extend_from_slice(src);
Ok(src.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}