grafbase_local_common/
utils.rs

1use crate::{consts::MAX_PORT, types::LocalAddressType};
2use std::{any::Any, net::TcpListener};
3
4/// determines if a port or port range are available
5#[must_use]
6pub fn find_available_port(search: bool, start_port: u16, local_address_type: LocalAddressType) -> Option<u16> {
7    if search {
8        find_available_port_in_range(start_port..MAX_PORT, local_address_type)
9    } else {
10        let local_address = local_address_type.to_ip_v4();
11        TcpListener::bind((local_address, start_port))
12            .is_ok()
13            .then_some(start_port)
14    }
15}
16
17/// finds an available port within a range
18#[must_use]
19pub fn find_available_port_in_range<R>(mut range: R, local_address_type: LocalAddressType) -> Option<u16>
20where
21    R: ExactSizeIterator<Item = u16>,
22{
23    let local_address = local_address_type.to_ip_v4();
24    range.find(|port| TcpListener::bind((local_address, *port)).is_ok())
25}
26
27/// converts an unknown panic parameter from [`std::thread::JoinHandle`] `join` to an [`Option<String>`]
28#[must_use]
29pub fn get_thread_panic_message(parameter: &Box<dyn Any + Send>) -> Option<String> {
30    let str_message = parameter.downcast_ref::<&'static str>();
31    let string_message = parameter.downcast_ref::<String>();
32    match (str_message, string_message) {
33        (Some(&message), None) => Some(message.to_string()),
34        (None, Some(message)) => Some(message.clone()),
35        _ => None,
36    }
37}