这段代码可以工作,但是TODO说明了这一切:函数本质上是相同的。
我可以使用声明性宏,但是我更喜欢使用泛型。有问题的是,Ipv6Addr和Ipv4Addr没有提供对所有重要octets方法的访问的特性。
我怎样才能克服这一切?
//TODO: these two function are identical
fn v6_netmask_width(netmask: network_interface::Netmask<Ipv6Addr>) -> i32 {
if let Some(netmask) = netmask {
netmask.octets().iter().map(|x| *x as i32).sum()
} else {
0
}
}
fn v4_netmask_width(netmask: network_interface::Netmask<Ipv4Addr>) -> i32 {
if let Some(netmask) = netmask {
netmask.octets().iter().map(|x| *x as i32).sum()
} else {
0
}
}发布于 2022-11-19 13:20:20
解决这个问题的方法有很多,但是您正在尝试执行泛型代码,以避免重复5行函数。任何宏或一般实现的样板可能会更长。
但是,如果您想要避免逻辑本身的重复,那么一个简单的解决方案是在本地调用octets(),然后一般地管理产生的字节数组:
fn xx_netmask_width<const SZ: usize>(netmask: Option<[u8; SZ]>) -> i32 {
if let Some(netmask) = netmask {
netmask.iter().map(|x| *x as i32).sum()
} else {
0
}
}
fn v6_netmask_width(netmask: Option<Ipv6Addr>) -> i32 {
xx_netmask_width(netmask.as_ref().map(Ipv6Addr::octets))
}
fn v4_netmask_width(netmask: Option<Ipv4Addr>) -> i32 {
xx_netmask_width(netmask.as_ref().map(Ipv4Addr::octets))
}当然,您可以编写一个特性Octetable并跳过一行。我认为这是不值得的,除非实际的逻辑再长一点。但只是为了表现:
trait Octetable {
type Output: IntoIterator<Item=u8>;
fn octets(&self) -> Self::Output;
}
impl Octetable for Ipv6Addr {
type Output = [u8; 16];
fn octets(&self) -> [u8; 16] {
Ipv6Addr::octets(self)
}
}
impl Octetable for Ipv4Addr {
type Output = [u8; 4];
fn octets(&self) -> [u8; 4] {
Ipv4Addr::octets(self)
}
}
fn netmask_width(netmask: Option<impl Octetable>) -> i32 {
if let Some(netmask) = netmask {
netmask.octets().into_iter().map(|x| x as i32).sum()
} else {
0
}
}https://stackoverflow.com/questions/74500103
复制相似问题