在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的。
答案 0 :(得分:6)
IpAddr
是IP地址的抽象。它是一个枚举,它包含Ipv4Addr
或Ipv6Addr
以及一些提供抽象访问权限的方法。
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 */ }
}
此外,IpAddr
为Copy
,因此您甚至无需担心使用其原始值(ip
变量),只会隐式复制它。