From 1eeade64a227f09c68a656903e3ac809fa6aa210 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Sat, 12 Oct 2024 04:04:25 +0300 Subject: [PATCH] Use `Bytes` to avoid double indirection with `Arc>` --- Cargo.toml | 1 + src/lib.rs | 64 +++++++++++++++++++++++++++++------------------------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 188ed4e..1c7dd96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ default = ["url"] [dependencies] arrayref = "0.3" byteorder = "1.5.0" +bytes = "1.7.2" data-encoding = "2.6.0" multibase = "0.9.1" multihash = "0.19" diff --git a/src/lib.rs b/src/lib.rs index 398324d..df596a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,18 +13,18 @@ mod from_url; pub use self::errors::{Error, Result}; pub use self::onion_addr::Onion3Addr; pub use self::protocol::Protocol; +use bytes::{BufMut, Bytes, BytesMut}; use serde::{ de::{self, Error as DeserializerError}, Deserialize, Deserializer, Serialize, Serializer, }; use std::{ convert::TryFrom, - fmt, io, + fmt, iter::FromIterator, net::{IpAddr, Ipv4Addr, Ipv6Addr}, result::Result as StdResult, str::FromStr, - sync::Arc, }; pub use libp2p_identity::PeerId; @@ -42,21 +42,21 @@ static_assertions::const_assert! { #[allow(clippy::rc_buffer)] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] pub struct Multiaddr { - bytes: Arc>, + bytes: Bytes, } impl Multiaddr { /// Create a new, empty multiaddress. pub fn empty() -> Self { Self { - bytes: Arc::new(Vec::new()), + bytes: Bytes::new(), } } /// Create a new, empty multiaddress with the given capacity. pub fn with_capacity(n: usize) -> Self { Self { - bytes: Arc::new(Vec::with_capacity(n)), + bytes: BytesMut::with_capacity(n).freeze(), } } @@ -88,10 +88,10 @@ impl Multiaddr { /// ``` /// pub fn push(&mut self, p: Protocol<'_>) { - let mut w = io::Cursor::<&mut Vec>::new(Arc::make_mut(&mut self.bytes)); - w.set_position(w.get_ref().len() as u64); - p.write_bytes(&mut w) - .expect("Writing to a `io::Cursor<&mut Vec>` never fails.") + let mut bytes = BytesMut::from(std::mem::take(&mut self.bytes)); + p.write_bytes(&mut (&mut bytes).writer()) + .expect("Writing to a `BytesMut` never fails."); + self.bytes = bytes.freeze(); } /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty. @@ -116,17 +116,19 @@ impl Multiaddr { } slice = s }; - let remaining_len = self.bytes.len() - slice.len(); - Arc::make_mut(&mut self.bytes).truncate(remaining_len); + let remaining_len = self.len() - slice.len(); + let mut bytes = BytesMut::from(std::mem::take(&mut self.bytes)); + bytes.truncate(remaining_len); + self.bytes = bytes.freeze(); Some(protocol) } /// Like [`Multiaddr::push`] but consumes `self`. pub fn with(mut self, p: Protocol<'_>) -> Self { - let mut w = io::Cursor::<&mut Vec>::new(Arc::make_mut(&mut self.bytes)); - w.set_position(w.get_ref().len() as u64); - p.write_bytes(&mut w) - .expect("Writing to a `io::Cursor<&mut Vec>` never fails."); + let mut bytes = BytesMut::from(std::mem::take(&mut self.bytes)); + p.write_bytes(&mut (&mut bytes).writer()) + .expect("Writing to a `BytesMut` never fails."); + self.bytes = bytes.freeze(); self } @@ -210,7 +212,7 @@ impl Multiaddr { /// Returns &str identifiers for the protocol names themselves. /// This omits specific info like addresses, ports, peer IDs, and the like. - /// Example: `"/ip4/127.0.0.1/tcp/5001"` would return `["ip4", "tcp"]` + /// Example: `"/ip4/127.0.0.1/tcp/5001"` would return `["ip4", "tcp"]` pub fn protocol_stack(&self) -> ProtoStackIter { ProtoStackIter { parts: self.iter() } } @@ -262,13 +264,13 @@ impl<'a> FromIterator> for Multiaddr { where T: IntoIterator>, { - let mut writer = Vec::new(); + let mut bytes = BytesMut::new(); for cmp in iter { - cmp.write_bytes(&mut writer) - .expect("Writing to a `Vec` never fails."); + cmp.write_bytes(&mut (&mut bytes).writer()) + .expect("Writing to a `BytesMut` never fails."); } Multiaddr { - bytes: Arc::new(writer), + bytes: bytes.freeze(), } } } @@ -277,7 +279,7 @@ impl FromStr for Multiaddr { type Err = Error; fn from_str(input: &str) -> Result { - let mut writer = Vec::new(); + let mut bytes = BytesMut::new(); let mut parts = input.split('/').peekable(); if Some("") != parts.next() { @@ -287,12 +289,12 @@ impl FromStr for Multiaddr { while parts.peek().is_some() { let p = Protocol::from_str_parts(&mut parts)?; - p.write_bytes(&mut writer) - .expect("Writing to a `Vec` never fails."); + p.write_bytes(&mut (&mut bytes).writer()) + .expect("Writing to a `BytesMut` never fails."); } Ok(Multiaddr { - bytes: Arc::new(writer), + bytes: bytes.freeze(), }) } } @@ -330,10 +332,12 @@ impl<'a> Iterator for ProtoStackIter<'a> { impl<'a> From> for Multiaddr { fn from(p: Protocol<'a>) -> Multiaddr { - let mut w = Vec::new(); - p.write_bytes(&mut w) - .expect("Writing to a `Vec` never fails."); - Multiaddr { bytes: Arc::new(w) } + let mut bytes = BytesMut::new(); + p.write_bytes(&mut (&mut bytes).writer()) + .expect("Writing to a `BytesMut` never fails."); + Multiaddr { + bytes: bytes.freeze(), + } } } @@ -368,7 +372,9 @@ impl TryFrom> for Multiaddr { let (_, s) = Protocol::from_bytes(slice)?; slice = s } - Ok(Multiaddr { bytes: Arc::new(v) }) + Ok(Multiaddr { + bytes: Bytes::from(v), + }) } }