create_rust_app/util/
net.rs

1use std::{
2    net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, TcpListener, ToSocketAddrs},
3    ops::Range,
4};
5
6/// binds a [`TcpListener`] to the given [`addr`](`ToSocketAddrs`)
7fn test_bind<A: ToSocketAddrs>(addr: A) -> bool {
8    TcpListener::bind(addr)
9        .map(|t| t.local_addr().is_ok())
10        .unwrap_or(false)
11}
12
13/// is the given port free on this machine
14#[must_use]
15pub fn is_port_free(port: u16) -> bool {
16    let ipv4 = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port);
17    let ipv6 = SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, port, 0, 0);
18
19    test_bind(ipv6) && test_bind(ipv4)
20}
21
22/// max range is 65535
23#[must_use]
24pub fn find_free_port(mut range: Range<u16>) -> Option<u16> {
25    range.find(|port| is_port_free(*port))
26}