about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
author南浦月 <nanpuyue@gmail.com>2020-08-10 20:20:20 +0800
committer南浦月 <nanpuyue@gmail.com>2020-08-11 09:15:08 +0800
commitd892a07c67dfa4f347b62ecf96de184c41dae5dd (patch)
tree3026164283a4e586d8e9f23eb6c93c6c7ca7ad4b /library/std/src
parentcfdf9d335501cc0a53ae69c940095cca7d4be0f8 (diff)
downloadrust-d892a07c67dfa4f347b62ecf96de184c41dae5dd.tar.gz
rust-d892a07c67dfa4f347b62ecf96de184c41dae5dd.zip
add Ipv6Addr::to_ipv4_mapped
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/net/ip.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index a64b43ca3ad..193e626d704 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -1488,6 +1488,37 @@ impl Ipv6Addr {
         (self.segments()[0] & 0xff00) == 0xff00
     }
 
+    /// Converts this address to an [IPv4 address] if it's an "IPv4-mapped IPv6 address"
+    /// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
+    ///
+    /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
+    /// All addresses *not* starting with `::ffff` will return `None`.
+    ///
+    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
+    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
+    /// ```
+    pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+        match self.octets() {
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+                Some(Ipv4Addr::new(a, b, c, d))
+            }
+            _ => None,
+        }
+    }
+
     /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
     /// neither IPv4-compatible or IPv4-mapped.
     ///
@@ -2085,6 +2116,15 @@ mod tests {
     }
 
     #[test]
+    fn ipv6_to_ipv4_mapped() {
+        assert_eq!(
+            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
+            Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+        );
+        assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
+    }
+
+    #[test]
     fn ipv6_to_ipv4() {
         assert_eq!(
             Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),