1use std::{
2 collections::HashSet,
3 env,
4 hash::Hash,
5 process::{Child, Command},
6};
7
8use rand::{
9 distr::{Alphanumeric, Uniform},
10 rng, RngExt as _,
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.div_ceil(2)).map(|_| rng.random()).collect();
45 let mut s = hex::encode(bytes);
46 s.truncate(n);
47 s
48}
49
50pub fn rand_string_all(n: usize) -> String {
52 rng()
53 .sample_iter(Uniform::new(char::from(33), char::from(127)).unwrap())
54 .take(n)
55 .collect()
56}
57
58pub fn restart() -> Result<Child> {
62 Command::new(env::current_exe()?)
63 .args(env::args().skip(1))
64 .spawn()
65 .map_err(Into::into)
66}
67
68#[cfg(feature = "rustls")]
69pub fn load_rustls_config<P: AsRef<std::path::Path>>(
74 cert: P,
75 key: P,
76) -> Result<rustls::ServerConfig> {
77 let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
78 let config = rustls::ServerConfig::builder().with_no_client_auth();
79 let cert_chain =
80 rustls_pemfile::certs(&mut std::io::BufReader::new(std::fs::File::open(cert)?))
81 .collect::<Result<Vec<_>, _>>()?;
82 let mut key_chain =
83 rustls_pemfile::pkcs8_private_keys(&mut std::io::BufReader::new(std::fs::File::open(key)?))
84 .map(|v| v.map(rustls::pki_types::PrivateKeyDer::Pkcs8))
85 .collect::<Result<Vec<_>, _>>()?;
86
87 let Some(private_key) = key_chain.pop() else {
88 anyhow::bail!("Cannot find PKCS 8 private key");
89 };
90
91 config
92 .with_single_cert(cert_chain, private_key)
93 .map_err(Into::into)
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_is_unique() {
102 assert!(is_unique(vec![1, 2, 3]));
103 assert!(is_unique([1, 2, 3]));
104 assert!(is_unique(vec![1]));
105 assert!(is_unique(Vec::<i32>::new()));
106 assert!(!is_unique(vec![1, 2, 2]));
107 assert!(!is_unique([1, 1]));
108 assert!(is_unique("abc".chars()));
109 assert!(!is_unique("aba".chars()));
110 assert!(is_unique("".chars()));
111 }
112
113 #[test]
114 fn test_is_default() {
115 assert!(is_default(&0_u8));
116 assert!(is_default(&0_i64));
117 assert!(!is_default(&1_i64));
118 assert!(is_default(&String::new()));
119 assert!(!is_default(&"a".to_string()));
120 assert!(is_default(&Vec::<i32>::new()));
121 assert!(!is_default(&vec![1]));
122 assert!(is_default(&Option::<i32>::None));
123 assert!(!is_default(&Some(1)));
124 }
125
126 #[test]
127 fn test_rand_string() {
128 for n in [0, 1, 2, 3, 4, 5, 10, 63, 64] {
129 let s = rand_string(n);
130 assert_eq!(s.len(), n);
131 assert!(s.chars().all(|c| c.is_ascii_alphanumeric()));
132 }
133 }
134
135 #[test]
136 fn test_rand_string_hex() {
137 for n in [0, 1, 2, 3, 4, 5, 10, 63, 64] {
138 let s = rand_string_hex(n);
139 assert_eq!(s.len(), n);
140 assert!(s.bytes().all(|b| b.is_ascii_hexdigit()));
141 }
142 }
143
144 #[test]
145 fn test_rand_string_all() {
146 let s = rand_string_all(4000);
147 assert!(s.chars().all(|c| ('!'..='~').contains(&c)),);
148 }
149}