Skip to content

Commit

Permalink
Use Bytes to avoid double indirection with Arc<Vec<u8>>
Browse files Browse the repository at this point in the history
  • Loading branch information
nazar-pc committed Oct 12, 2024
1 parent def1fff commit 1eeade6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 29 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
64 changes: 35 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -42,21 +42,21 @@ static_assertions::const_assert! {
#[allow(clippy::rc_buffer)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct Multiaddr {
bytes: Arc<Vec<u8>>,
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(),
}
}

Expand Down Expand Up @@ -88,10 +88,10 @@ impl Multiaddr {
/// ```
///
pub fn push(&mut self, p: Protocol<'_>) {
let mut w = io::Cursor::<&mut Vec<u8>>::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<u8>>` 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.
Expand All @@ -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<u8>>::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<u8>>` 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
}

Expand Down Expand Up @@ -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() }
}
Expand Down Expand Up @@ -262,13 +264,13 @@ impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
where
T: IntoIterator<Item = Protocol<'a>>,
{
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(),
}
}
}
Expand All @@ -277,7 +279,7 @@ impl FromStr for Multiaddr {
type Err = Error;

fn from_str(input: &str) -> Result<Self> {
let mut writer = Vec::new();
let mut bytes = BytesMut::new();
let mut parts = input.split('/').peekable();

if Some("") != parts.next() {
Expand All @@ -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(),
})
}
}
Expand Down Expand Up @@ -330,10 +332,12 @@ impl<'a> Iterator for ProtoStackIter<'a> {

impl<'a> From<Protocol<'a>> 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(),
}
}
}

Expand Down Expand Up @@ -368,7 +372,9 @@ impl TryFrom<Vec<u8>> for Multiaddr {
let (_, s) = Protocol::from_bytes(slice)?;
slice = s
}
Ok(Multiaddr { bytes: Arc::new(v) })
Ok(Multiaddr {
bytes: Bytes::from(v),
})
}
}

Expand Down

0 comments on commit 1eeade6

Please sign in to comment.