tentacle_multiaddr/
lib.rs

1//! Mini Implementation of [multiaddr](https://github.com/jbenet/multiaddr) in Rust.
2mod error;
3mod onion_addr;
4mod protocol;
5
6pub use self::error::Error;
7pub use self::onion_addr::Onion3Addr;
8pub use self::protocol::Protocol;
9use bytes::{Bytes, BytesMut};
10use serde::{
11    Deserialize, Deserializer, Serialize, Serializer,
12    de::{self, Error as DeserializerError},
13};
14use std::{
15    fmt,
16    iter::FromIterator,
17    net::{IpAddr, Ipv4Addr, Ipv6Addr},
18    result::Result as StdResult,
19    str::FromStr,
20};
21
22pub type MultiAddr = Multiaddr;
23
24/// Representation of a Multiaddr.
25#[derive(PartialEq, Eq, Clone, Hash)]
26pub struct Multiaddr {
27    bytes: Bytes,
28}
29
30impl Multiaddr {
31    /// Returns true if the multiaddres has no data.
32    pub fn is_empty(&self) -> bool {
33        self.bytes.is_empty()
34    }
35
36    /// Return the length in bytes of this multiaddress.
37    pub fn len(&self) -> usize {
38        self.bytes.len()
39    }
40
41    /// Return a copy of this [`Multiaddr`]'s byte representation.
42    pub fn to_vec(&self) -> Vec<u8> {
43        Vec::from(&self.bytes[..])
44    }
45
46    /// Adds an already-parsed address component to the end of this multiaddr.
47    ///
48    /// # Examples
49    ///
50    /// ```
51    /// use tentacle_multiaddr::{Multiaddr, Protocol};
52    ///
53    /// let mut address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
54    /// address.push(Protocol::Tcp(10000));
55    /// println!("{}", address);
56    /// assert_eq!(address, "/ip4/127.0.0.1/tcp/10000".parse().unwrap());
57    /// ```
58    ///
59    pub fn push(&mut self, p: Protocol<'_>) {
60        let mut w = vec![0; self.bytes.len()];
61        w.copy_from_slice(&self.bytes[..]);
62        p.write_to_bytes(&mut w);
63        self.bytes = Bytes::from(w);
64    }
65
66    /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty.
67    /// ```
68    /// use std::net::Ipv4Addr;
69    /// use tentacle_multiaddr::{Multiaddr, Protocol};
70    ///
71    /// let mut address: Multiaddr = "/ip4/127.0.0.1/tcp/5678".parse().unwrap();
72    ///
73    /// assert_eq!(address.pop().unwrap(), Protocol::Tcp(5678));
74    /// assert_eq!(address.pop().unwrap(), Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)));
75    /// ```
76    ///
77    pub fn pop<'a>(&mut self) -> Option<Protocol<'a>> {
78        let mut slice = &self.bytes[..]; // the remaining multiaddr slice
79        if slice.is_empty() {
80            return None;
81        }
82        let protocol = loop {
83            let (p, s) = Protocol::from_bytes(slice).expect("`slice` is a valid `Protocol`.");
84            if s.is_empty() {
85                break p.acquire();
86            }
87            slice = s
88        };
89        let remaining_len = self.bytes.len() - slice.len();
90        self.bytes.truncate(remaining_len);
91        Some(protocol)
92    }
93
94    /// Returns the components of this multiaddress.
95    ///
96    /// ```
97    /// use std::net::Ipv4Addr;
98    /// use tentacle_multiaddr::{Multiaddr, Protocol};
99    ///
100    /// let address: Multiaddr = "/ip4/127.0.0.1/tcp/5678".parse().unwrap();
101    ///
102    /// let components = address.iter().collect::<Vec<_>>();
103    /// assert_eq!(components[0], Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)));
104    /// assert_eq!(components[1], Protocol::Tcp(5678));
105    /// ```
106    ///
107    pub fn iter(&self) -> Iter<'_> {
108        Iter(&self.bytes)
109    }
110
111    /// Replace a [`Protocol`] at some position in this `Multiaddr`.
112    ///
113    /// The parameter `at` denotes the index of the protocol at which the function
114    /// `by` will be applied to the current protocol, returning an optional replacement.
115    ///
116    /// If `at` is out of bounds or `by` does not yield a replacement value,
117    /// `None` will be returned. Otherwise a copy of this `Multiaddr` with the
118    /// updated `Protocol` at position `at` will be returned.
119    pub fn replace<'a, F>(&self, at: usize, by: F) -> Option<Multiaddr>
120    where
121        F: FnOnce(&Protocol) -> Option<Protocol<'a>>,
122    {
123        let mut address = BytesMut::with_capacity(self.bytes.len());
124        let mut fun = Some(by);
125        let mut replaced = false;
126
127        for (i, p) in self.iter().enumerate() {
128            if i == at {
129                let f = fun.take().expect("i == at only happens once");
130                if let Some(q) = f(&p) {
131                    q.write_to_bytes(&mut address);
132                    replaced = true;
133                    continue;
134                }
135                return None;
136            }
137            p.write_to_bytes(&mut address);
138        }
139
140        if replaced {
141            Some(Multiaddr {
142                bytes: address.freeze(),
143            })
144        } else {
145            None
146        }
147    }
148}
149
150impl fmt::Debug for Multiaddr {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        self.to_string().fmt(f)
153    }
154}
155
156impl fmt::Display for Multiaddr {
157    /// Convert a Multiaddr to a string
158    ///
159    /// # Examples
160    ///
161    /// ```
162    /// use tentacle_multiaddr::Multiaddr;
163    ///
164    /// let address: Multiaddr = "/ip4/127.0.0.1/tcp/80".parse().unwrap();
165    /// assert_eq!(address.to_string(), "/ip4/127.0.0.1/tcp/80");
166    /// ```
167    ///
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        for s in self.iter() {
170            s.to_string().fmt(f)?;
171        }
172        Ok(())
173    }
174}
175
176impl AsRef<[u8]> for Multiaddr {
177    fn as_ref(&self) -> &[u8] {
178        self.bytes.as_ref()
179    }
180}
181
182impl<'a> IntoIterator for &'a Multiaddr {
183    type Item = Protocol<'a>;
184    type IntoIter = Iter<'a>;
185
186    fn into_iter(self) -> Iter<'a> {
187        Iter(&self.bytes)
188    }
189}
190
191impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
192    fn from_iter<T>(iter: T) -> Self
193    where
194        T: IntoIterator<Item = Protocol<'a>>,
195    {
196        let mut writer = BytesMut::new();
197        for cmp in iter {
198            cmp.write_to_bytes(&mut writer);
199        }
200        Multiaddr {
201            bytes: writer.freeze(),
202        }
203    }
204}
205
206impl FromStr for Multiaddr {
207    type Err = Error;
208
209    fn from_str(input: &str) -> Result<Self, Error> {
210        let mut writer = BytesMut::new();
211        let mut parts = input.split('/').peekable();
212
213        if Some("") != parts.next() {
214            // A multiaddr must start with `/`
215            return Err(Error::InvalidMultiaddr);
216        }
217
218        while parts.peek().is_some() {
219            let p = Protocol::from_str_peek(&mut parts)?;
220            p.write_to_bytes(&mut writer);
221        }
222
223        Ok(Multiaddr {
224            bytes: writer.freeze(),
225        })
226    }
227}
228
229/// Iterator over `Multiaddr` [`Protocol`]s.
230pub struct Iter<'a>(&'a [u8]);
231
232impl<'a> Iterator for Iter<'a> {
233    type Item = Protocol<'a>;
234
235    fn next(&mut self) -> Option<Self::Item> {
236        if self.0.is_empty() {
237            return None;
238        }
239
240        let (p, next_data) =
241            Protocol::from_bytes(self.0).expect("`Multiaddr` is known to be valid.");
242
243        self.0 = next_data;
244        Some(p)
245    }
246}
247
248impl<'a> From<Protocol<'a>> for Multiaddr {
249    fn from(p: Protocol<'a>) -> Multiaddr {
250        let mut w = BytesMut::new();
251        p.write_to_bytes(&mut w);
252        Multiaddr { bytes: w.freeze() }
253    }
254}
255
256impl From<IpAddr> for Multiaddr {
257    fn from(v: IpAddr) -> Multiaddr {
258        match v {
259            IpAddr::V4(a) => a.into(),
260            IpAddr::V6(a) => a.into(),
261        }
262    }
263}
264
265impl From<Ipv4Addr> for Multiaddr {
266    fn from(v: Ipv4Addr) -> Multiaddr {
267        Protocol::Ip4(v).into()
268    }
269}
270
271impl From<Ipv6Addr> for Multiaddr {
272    fn from(v: Ipv6Addr) -> Multiaddr {
273        Protocol::Ip6(v).into()
274    }
275}
276
277impl TryFrom<Bytes> for Multiaddr {
278    type Error = Error;
279
280    fn try_from(v: Bytes) -> Result<Self, Error> {
281        // Check if the argument is a valid `Multiaddr` by reading its protocols.
282        let mut slice = &v[..];
283        while !slice.is_empty() {
284            let (_, s) = Protocol::from_bytes(slice)?;
285            slice = s
286        }
287        Ok(Multiaddr { bytes: v })
288    }
289}
290
291impl TryFrom<BytesMut> for Multiaddr {
292    type Error = Error;
293
294    fn try_from(v: BytesMut) -> Result<Self, Error> {
295        Multiaddr::try_from(v.freeze())
296    }
297}
298
299impl TryFrom<Vec<u8>> for Multiaddr {
300    type Error = Error;
301
302    fn try_from(v: Vec<u8>) -> Result<Self, Error> {
303        Multiaddr::try_from(Bytes::from(v))
304    }
305}
306
307impl TryFrom<String> for Multiaddr {
308    type Error = Error;
309
310    fn try_from(s: String) -> Result<Multiaddr, Error> {
311        s.parse()
312    }
313}
314
315impl<'a> TryFrom<&'a str> for Multiaddr {
316    type Error = Error;
317
318    fn try_from(s: &'a str) -> Result<Multiaddr, Error> {
319        s.parse()
320    }
321}
322
323impl Serialize for Multiaddr {
324    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
325    where
326        S: Serializer,
327    {
328        if serializer.is_human_readable() {
329            serializer.serialize_str(&self.to_string())
330        } else {
331            serializer.serialize_bytes(self.as_ref())
332        }
333    }
334}
335
336impl<'de> Deserialize<'de> for Multiaddr {
337    fn deserialize<D>(deserializer: D) -> StdResult<Self, D::Error>
338    where
339        D: Deserializer<'de>,
340    {
341        struct Visitor {
342            is_human_readable: bool,
343        }
344
345        impl<'de> de::Visitor<'de> for Visitor {
346            type Value = Multiaddr;
347
348            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
349                formatter.write_str("multiaddress")
350            }
351            fn visit_seq<A: de::SeqAccess<'de>>(
352                self,
353                mut seq: A,
354            ) -> StdResult<Self::Value, A::Error> {
355                let mut buf: Vec<u8> = Vec::with_capacity(seq.size_hint().unwrap_or(0));
356                while let Some(e) = seq.next_element()? {
357                    buf.push(e);
358                }
359                if self.is_human_readable {
360                    let s = String::from_utf8(buf).map_err(DeserializerError::custom)?;
361                    s.parse().map_err(DeserializerError::custom)
362                } else {
363                    Multiaddr::try_from(buf).map_err(DeserializerError::custom)
364                }
365            }
366            fn visit_str<E: de::Error>(self, v: &str) -> StdResult<Self::Value, E> {
367                v.parse().map_err(DeserializerError::custom)
368            }
369            fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> StdResult<Self::Value, E> {
370                self.visit_str(v)
371            }
372            fn visit_string<E: de::Error>(self, v: String) -> StdResult<Self::Value, E> {
373                self.visit_str(&v)
374            }
375            fn visit_bytes<E: de::Error>(self, v: &[u8]) -> StdResult<Self::Value, E> {
376                self.visit_byte_buf(v.into())
377            }
378            fn visit_borrowed_bytes<E: de::Error>(self, v: &'de [u8]) -> StdResult<Self::Value, E> {
379                self.visit_byte_buf(v.into())
380            }
381            fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> StdResult<Self::Value, E> {
382                Multiaddr::try_from(v).map_err(DeserializerError::custom)
383            }
384        }
385
386        if deserializer.is_human_readable() {
387            deserializer.deserialize_str(Visitor {
388                is_human_readable: true,
389            })
390        } else {
391            deserializer.deserialize_bytes(Visitor {
392                is_human_readable: false,
393            })
394        }
395    }
396}
397
398/// Easy way for a user to create a `Multiaddr`.
399///
400/// Example:
401///
402/// ```rust
403/// # use tentacle_multiaddr::multiaddr;
404/// let addr = multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16));
405/// ```
406///
407/// Each element passed to `multiaddr!` should be a variant of the `Protocol` enum. The
408/// optional parameter is turned into the proper type with the `Into` trait.
409///
410/// For example, `Ip4([127, 0, 0, 1])` works because `Ipv4Addr` implements `From<[u8; 4]>`.
411#[macro_export]
412macro_rules! multiaddr {
413    ($($comp:ident $(($param:expr))*),+) => {
414        {
415            use std::iter;
416            let elem = iter::empty::<$crate::Protocol>();
417            $(
418                let elem = {
419                    let cmp = $crate::Protocol::$comp $(( $param.into() ))*;
420                    elem.chain(iter::once(cmp))
421                };
422            )+
423            elem.collect::<$crate::Multiaddr>()
424        }
425    }
426}
427
428#[cfg(test)]
429mod test {
430    use super::{Multiaddr, Protocol};
431    use parity_multiaddr::{Multiaddr as OtherMultiaddr, Protocol as OtherProtocol};
432
433    #[test]
434    fn compatibility_test() {
435        let mut address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
436        address.push(Protocol::Tcp(10000));
437        assert_eq!(address, "/ip4/127.0.0.1/tcp/10000".parse().unwrap());
438
439        let _address: Multiaddr = "/ip4/127.0.0.1/tcp/20/tls/main".parse().unwrap();
440
441        let mut address_1: Multiaddr =
442            "/ip4/47.111.169.36/tcp/8111/p2p/QmNQ4jky6uVqLDrPU7snqxARuNGWNLgSrTnssbRuy3ij2W"
443                .parse()
444                .unwrap();
445
446        let mut address_2: OtherMultiaddr =
447            "/ip4/47.111.169.36/tcp/8111/p2p/QmNQ4jky6uVqLDrPU7snqxARuNGWNLgSrTnssbRuy3ij2W"
448                .parse()
449                .unwrap();
450
451        let p_1 = address_1.pop().unwrap();
452        let p_2 = address_2.pop().unwrap();
453
454        match (p_1, p_2) {
455            (Protocol::P2P(s_1), OtherProtocol::P2p(s_2)) => assert_eq!(s_1, s_2.to_bytes()),
456            e => panic!("not expect protocol: {:?}", e),
457        }
458    }
459}