如何将IpAddr转换为IPv4Addr?

时间:2018-02-23 23:12:46

标签: rust

在Rust中,可以轻松地从IpAddr创建IpV4Addr

let ipv4 = IpV4Addr::new(127,0,0,1);
let ip = IpAddr::V4(ipv4);

但似乎没有办法回来:

if ip.is_ipv4() {
    let ipv4: IpV4Addr = .....?
}

原因是我需要在某个时刻(通过IPv4::octets)访问IPv4地址的八位字节以通过网络传输它们。但是,我想在应用程序的其他部分使用更通用的IpAddr表示,因为我希望将来实现IPv6,因此使网络代码不是特定于IPv4的。

2 个答案:

答案 0 :(得分:6)

IpAddr是IP地址的抽象。它是一个枚举,它包含Ipv4AddrIpv6Addr以及一些提供抽象访问权限的方法。

Rust不允许你将IpAddr投射到Ipv4Addr,因为如果它实际上是Ipv6Addr怎么办?你也必须处理这个案子。您确信Rust已经使用match处理了所有可能性。

use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

fn main() {
    let ips = [
        IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
        IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)),
    ];

    for ip in ips.iter() {
        match *ip {
            IpAddr::V4(ip4) => println!("ipv4: {}, octets: {:?}", ip4, ip4.octets()),
            IpAddr::V6(ip6) => println!("ipv6: {}, segments: {:?}", ip6, ip6.segments()),
        }
    }
}

不需要默认情况,因为Rust类型检查器知道没有其他可能性。 ips是一个IpAddr数组,只包含两种可能性,即V4或V6。事实上,如果你把一个放在那里,Rust会发出警告,所以如果将来IpAddr发生变化,你会发现编译错误。

答案 1 :(得分:4)

IpAddr是枚举,因此您可以使用模式匹配:

if let IpAddr::V4(ipv4) = ip {
    // here ipv4 is of type IpV4Addr
}

// or, if you need to handle IPv6 as well

match ip {
    IpAddr::V4(ipv4) => { /* handle IPv4 */ }
    IpAddr::V6(ipv6) => { /* handle IPv6 */ }
}

此外,IpAddrCopy,因此您甚至无需担心使用其原始值(ip变量),只会隐式复制它。