1use crate::{Ops, Port, Range};
2use std::str::FromStr;
3use std::{net::Ipv4Addr, net::TcpListener};
4
5pub struct TcpPort;
6impl Ops for TcpPort {
7 fn any(host: &str) -> Option<Port> {
8 let r = Range::default();
9 (r.min..=r.max)
10 .filter(|&p| TcpPort::is_port_available(host, p))
11 .nth(0)
12 }
13
14 fn in_range(host: &str, r: Range) -> Option<Port> {
15 (r.min..=r.max)
16 .filter(|&p| TcpPort::is_port_available(host, p))
17 .nth(0)
18 }
19
20 fn from_list(host: &str, v: Vec<Port>) -> Option<Port> {
21 v.into_iter()
22 .filter(|&p| TcpPort::is_port_available(host, p))
23 .nth(0)
24 }
25
26 fn except(host: &str, v: Vec<Port>) -> Option<Port> {
27 let r = Range::default();
28 (r.min..=r.max)
29 .filter(|&p| !v.contains(&p) && TcpPort::is_port_available(host, p))
30 .nth(0)
31 }
32
33 fn in_range_except(host: &str, r: Range, v: Vec<Port>) -> Option<Port> {
34 (r.min..=r.max)
35 .filter(|&p| !v.contains(&p) && TcpPort::is_port_available(host, p))
36 .nth(0)
37 }
38
39 fn is_port_available(host: &str, p: Port) -> bool {
40 matches!(
41 TcpListener::bind((Ipv4Addr::from_str(host).unwrap(), p)).is_ok(),
42 true
43 )
44 }
45}