Specialize on truncate arg for ~5% speedup in truncate case

Use a generic param to specialize on the truncate arg to avoid needing
to check it and/or host bits if we'll end up accepting it regardless
when truncate is enabled.

Refactor host bits check into iputils.
This commit is contained in:
Keenan Tims 2023-11-16 19:19:24 -08:00
parent a75fdadcf8
commit 09da703b20
Signed by: ktims
GPG Key ID: 11230674D69038D4
2 changed files with 18 additions and 11 deletions

View File

@ -140,6 +140,9 @@ impl IpOrNet {
pub fn network(&self) -> IpAddr { pub fn network(&self) -> IpAddr {
self.0.network() self.0.network()
} }
pub fn has_host_bits(&self) -> bool {
self.0.addr() != self.0.network()
}
} }
impl FromStr for IpOrNet { impl FromStr for IpOrNet {

View File

@ -60,16 +60,17 @@ struct App {
} }
impl App { impl App {
fn add_prefix(&mut self, pfx: IpOrNet) { fn add_prefix<const TRUNCATE: bool>(&mut self, pfx: IpOrNet) {
// Parser accepts host bits set, so detect that case and error if not truncate mode // Parser accepts host bits set, so detect that case and error if not truncate mode
// Note: aggregate6 errors in this case regardless of -4, -6 so do the same // Note: aggregate6 errors in this case regardless of -4, -6 so do the same
if !self.args.truncate { if !TRUNCATE && pfx.has_host_bits() {
if pfx.addr() != pfx.network() { // We don't have the original string any more so our error
eprintln!("ERROR: '{}' is not a valid IP network, ignoring.", pfx); // differs from `aggregate6` in that it prints the pfxlen as
return; // parsed, not as in the source.
} eprintln!("ERROR: '{}' is not a valid IP network, ignoring.", pfx);
return;
} }
// Don't bother saving if we won't display.
if self.args.only_v4 && pfx.is_ipv6() { if self.args.only_v4 && pfx.is_ipv6() {
return; return;
} else if self.args.only_v6 && pfx.is_ipv4() { } else if self.args.only_v6 && pfx.is_ipv4() {
@ -79,14 +80,14 @@ impl App {
self.prefixes.add(pfx); self.prefixes.add(pfx);
} }
} }
fn consume_input(&mut self, input: &mut Input) { fn consume_input<const TRUNCATE: bool>(&mut self, input: &mut Input) {
for line in input.lock().lines() { for line in input.lock().lines() {
match line { match line {
Ok(line) => { Ok(line) => {
for net in line.split_whitespace() { for net in line.split_ascii_whitespace() {
let pnet = net.parse::<IpOrNet>(); let pnet = net.parse::<IpOrNet>();
match pnet { match pnet {
Ok(pnet) => self.add_prefix(pnet), Ok(pnet) => self.add_prefix::<TRUNCATE>(pnet),
Err(_e) => { Err(_e) => {
eprintln!("ERROR: '{}' is not a valid IP network, ignoring.", net); eprintln!("ERROR: '{}' is not a valid IP network, ignoring.", net);
} }
@ -103,7 +104,10 @@ impl App {
fn simplify_inputs(&mut self) { fn simplify_inputs(&mut self) {
let inputs = self.args.input.to_owned(); let inputs = self.args.input.to_owned();
for mut input in inputs { for mut input in inputs {
self.consume_input(&mut input); match self.args.truncate {
true => self.consume_input::<true>(&mut input),
false => self.consume_input::<false>(&mut input),
}
} }
self.prefixes.simplify(); self.prefixes.simplify();
} }