use std::sync::Arc;
use crate::error::{RLanLibError, Result};
#[derive(Debug)]
pub struct PortTargets(Vec<String>, usize);
fn loop_ports<F: FnMut(u16) -> Result<()>>(
list: &[String],
mut cb: F,
) -> Result<()> {
for target in list.iter() {
if target.contains("-") {
let parts: Vec<&str> = target.split("-").collect();
let begin = parts[0].parse::<u16>().map_err(|e| {
RLanLibError::from_port_parse_int_err(&target.to_string(), e)
})?;
let end = parts[1].parse::<u16>().map_err(|e| {
RLanLibError::from_port_parse_int_err(&target.to_string(), e)
})?;
for port in begin..=end {
cb(port)?;
}
} else {
let port = target.parse::<u16>().map_err(|e| {
RLanLibError::from_port_parse_int_err(&target.to_string(), e)
})?;
cb(port)?;
}
}
Ok(())
}
impl PortTargets {
pub fn new(list: Vec<String>) -> Result<Arc<Self>> {
let mut len = 0;
loop_ports(&list, |_| {
len += 1;
Ok(())
})?;
Ok(Arc::new(Self(list, len)))
}
pub fn is_empty(&self) -> bool {
self.1 == 0
}
pub fn len(&self) -> usize {
self.1
}
pub fn lazy_loop<F: FnMut(u16) -> Result<()>>(&self, cb: F) -> Result<()> {
loop_ports(&self.0, cb)
}
}
#[cfg(test)]
#[path = "./ports_tests.rs"]
mod tests;