1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#![crate_name = "unique_port"]
use once_cell::sync::Lazy;
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener};
use std::ops::Range;
use std::sync::Mutex;
static PORT_IDX: Lazy<Mutex<u16>> = Lazy::new(|| Mutex::new(1000));
pub fn get_unique_free_port() -> Result<u16, String> {
let mut port_idx = PORT_IDX
.lock()
.map_err(|_| "Failed to aquire the lock".to_owned())?;
let result = get_free_port(*port_idx..u16::MAX);
if let Ok(port) = result {
*port_idx = port + 1;
}
result
}
fn get_free_port(ports: Range<u16>) -> Result<u16, String> {
ports
.into_iter()
.find(|port| TcpListener::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, *port)).is_ok())
.ok_or_else(|| "Failed to get empty port".to_owned())
}