Sea*_*act 2 ip-address pattern-matching rust
我想net::Ipv4Addr::LOCALHOST
在模式匹配时使用常量过滤掉 IPv4 localhost 地址:
use get_if_addrs; // 0.5.3
use std::net;
fn main() -> std::io::Result<()> {
assert_eq!(
"127.0.0.1".parse::<net::Ipv4Addr>().unwrap(),
net::Ipv4Addr::LOCALHOST
);
{
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: _,
netmask: _,
broadcast: None,
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: net::Ipv4Addr::LOCALHOST,
netmask: _,
broadcast: _,
}) => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
我收到一个错误
use get_if_addrs; // 0.5.3
use std::net;
fn main() -> std::io::Result<()> {
assert_eq!(
"127.0.0.1".parse::<net::Ipv4Addr>().unwrap(),
net::Ipv4Addr::LOCALHOST
);
{
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: _,
netmask: _,
broadcast: None,
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: net::Ipv4Addr::LOCALHOST,
netmask: _,
broadcast: _,
}) => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
std::net::Ipv4Addr
确实有PartialEq
and 的实现Eq
,那么这个错误是什么意思?我该如何解决?
正如错误消息所述:
必须注释
#[derive(PartialEq, Eq)]
这不适用于Ipv4Addr
,它手动实现它,而不是派生它。
相反,使用匹配守卫:
use get_if_addrs; // 0.5.3
fn main() -> std::io::Result<()> {
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
broadcast: None, ..
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr { ip, .. }) if ip.is_loopback() => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
你也可以考虑引入一些嵌套:
use get_if_addrs::{IfAddr, Ifv4Addr}; // 0.5.3
fn main() -> std::io::Result<()> {
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
IfAddr::V4(addr) => match addr {
Ifv4Addr {
broadcast: None, ..
} => (),
Ifv4Addr { ip, .. } if ip.is_loopback() => (),
addr => println!("{:?}", addr),
},
IfAddr::V6(_) => (),
}
}
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
RFC 1445更详细地解释了基本决策:
- 引入
#[structural_match]
可应用于结构或枚举的功能门控属性,T
以指示T
可以在模式中使用类型的常量。- 已
#[derive(Eq)]
自动将此属性应用于它装饰的结构或枚举。自动插入的属性不需要使用特征门。- 将 struct 或 enum 类型的常量扩展为等效模式时,要求 struct 或 enum 类型用
#[structural_match]
. 内置类型的常量总是被扩展的。这些变化的实际效果会防止模式的使用的常数的,除非这些常数的类型是一个内置型(如
i32
或&str
),或者用户定义的常数,其Eq
被衍生(不仅仅是实现)。