1use std::{
2 collections::HashSet,
3 env,
4 hash::Hash,
5 process::{Child, Command},
6};
7
8use rand::{
9 distr::{Alphanumeric, Uniform},
10 rng, Rng,
11};
12
13use crate::Result;
14
15pub fn is_unique<T>(iter: T) -> bool
17where
18 T: IntoIterator,
19 T::Item: Eq + Hash,
20{
21 let mut uniq = HashSet::new();
22 iter.into_iter().all(move |x| uniq.insert(x))
23}
24
25pub fn is_default<T: Default + PartialEq>(t: &T) -> bool {
27 *t == Default::default()
28}
29
30pub fn rand_string(n: usize) -> String {
33 rng()
34 .sample_iter(&Alphanumeric)
35 .take(n)
36 .map(char::from)
37 .collect()
38}
39
40pub fn rand_string_hex(n: usize) -> String {
43 let mut rng = rng();
44 let bytes: Vec<u8> = (0..n / 2).map(|_| rng.random()).collect();
45 hex::encode(bytes)
46}
47
48pub fn rand_string_all(n: usize) -> String {
50 rng()
51 .sample_iter(Uniform::new(char::from(33), char::from(126)).unwrap())
52 .take(n)
53 .collect()
54}
55
56pub fn restart() -> Result<Child> {
60 Command::new(env::current_exe().unwrap())
61 .args(env::args().skip(1))
62 .spawn()
63 .map_err(Into::into)
64}
65
66#[cfg(feature = "rustls")]
67pub fn load_rustls_config<P: AsRef<std::path::Path>>(
69 cert: P,
70 key: P,
71) -> Result<rustls::ServerConfig> {
72 rustls::crypto::aws_lc_rs::default_provider()
73 .install_default()
74 .unwrap();
75 let config = rustls::ServerConfig::builder().with_no_client_auth();
76 let cert_chain =
77 rustls_pemfile::certs(&mut std::io::BufReader::new(std::fs::File::open(cert)?))
78 .collect::<Result<Vec<_>, _>>()?;
79 let mut key_chain =
80 rustls_pemfile::pkcs8_private_keys(&mut std::io::BufReader::new(std::fs::File::open(key)?))
81 .map(|v| v.map(rustls::pki_types::PrivateKeyDer::Pkcs8))
82 .collect::<Result<Vec<_>, _>>()?;
83
84 let Some(private_key) = key_chain.pop() else {
85 anyhow::bail!("Cannot find PKCS 8 private key");
86 };
87
88 config
89 .with_single_cert(cert_chain, private_key)
90 .map_err(Into::into)
91}