mod range_iterator;
use crate::input::{PortRange, ScanOrder};
use rand::rng;
use rand::seq::SliceRandom;
use range_iterator::RangeIterator;
#[derive(Debug)]
pub enum PortStrategy {
Manual(Vec<u16>),
Serial(SerialRange),
Random(RandomRange),
}
impl PortStrategy {
pub fn pick(range: &Option<PortRange>, ports: Option<Vec<u16>>, order: ScanOrder) -> Self {
match order {
ScanOrder::Serial if ports.is_none() => {
let range = range.as_ref().unwrap();
PortStrategy::Serial(SerialRange {
start: range.start,
end: range.end,
})
}
ScanOrder::Random if ports.is_none() => {
let range = range.as_ref().unwrap();
PortStrategy::Random(RandomRange {
start: range.start,
end: range.end,
})
}
ScanOrder::Serial => PortStrategy::Manual(ports.unwrap()),
ScanOrder::Random => {
let mut rng = rng();
let mut ports = ports.unwrap();
ports.shuffle(&mut rng);
PortStrategy::Manual(ports)
}
}
}
pub fn order(&self) -> Vec<u16> {
match self {
PortStrategy::Manual(ports) => ports.clone(),
PortStrategy::Serial(range) => range.generate(),
PortStrategy::Random(range) => range.generate(),
}
}
}
trait RangeOrder {
fn generate(&self) -> Vec<u16>;
}
#[derive(Debug)]
pub struct SerialRange {
start: u16,
end: u16,
}
impl RangeOrder for SerialRange {
fn generate(&self) -> Vec<u16> {
(self.start..=self.end).collect()
}
}
#[derive(Debug)]
pub struct RandomRange {
start: u16,
end: u16,
}
impl RangeOrder for RandomRange {
fn generate(&self) -> Vec<u16> {
RangeIterator::new(self.start.into(), self.end.into()).collect()
}
}
#[cfg(test)]
mod tests {
use super::PortStrategy;
use crate::input::{PortRange, ScanOrder};
#[test]
fn serial_strategy_with_range() {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Serial);
let result = strategy.order();
let expected_range = (1..=100).collect::<Vec<u16>>();
assert_eq!(expected_range, result);
}
#[test]
fn random_strategy_with_range() {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(&Some(range), None, ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..=100).collect::<Vec<u16>>();
assert_ne!(expected_range, result);
result.sort_unstable();
assert_eq!(expected_range, result);
}
#[test]
fn serial_strategy_with_ports() {
let strategy = PortStrategy::pick(&None, Some(vec![80, 443]), ScanOrder::Serial);
let result = strategy.order();
assert_eq!(vec![80, 443], result);
}
#[test]
fn random_strategy_with_ports() {
let strategy = PortStrategy::pick(&None, Some((1..10).collect()), ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..10).collect::<Vec<u16>>();
assert_ne!(expected_range, result);
result.sort_unstable();
assert_eq!(expected_range, result);
}
}