anarchist_readable_name_generator_lib/lib.rs
1//! This library uses the authors from Anarchist Library to generate a random name
2//!
3//! The intention here is to have a random name for situations you need to spin up some cloud compute resources and don't have a name in mind. Typically, for throwaway purposes.
4//!
5//! # Examples
6//!
7//! It's possible to simply generate a random name
8//!
9//! ```
10//! use anarchist_readable_name_generator_lib::readable_name;
11//!
12//! assert!(readable_name().len() > 0)
13//! ```
14//!
15//! You can also pass a seed or change the separator to give you predictability or minor customization.
16//!
17//! ```
18//! use anarchist_readable_name_generator_lib::readable_name_custom;
19//! use rand::prelude::*;
20//! use rand_chacha::ChaChaRng;
21//!
22//! let rng = ChaChaRng::seed_from_u64(2);
23//! assert_eq!(
24//! readable_name_custom("+", rng),
25//! "romantic+kamalmaz"
26//! );
27//! ```
28
29#![warn(clippy::nursery)]
30#![deny(
31 unused,
32 nonstandard_style,
33 future_incompatible,
34 missing_copy_implementations,
35 missing_debug_implementations,
36 missing_docs,
37 clippy::cargo,
38 clippy::complexity,
39 clippy::correctness,
40 clippy::perf,
41 clippy::style,
42 clippy::suspicious,
43 clippy::pedantic,
44 non_fmt_panics
45)]
46#![allow(clippy::multiple_crate_versions)]
47
48mod names;
49
50use names::ADJECTIVES;
51use names::NAMES;
52use rand::Rng;
53use rand::seq::IndexedRandom;
54
55/// Generate a readable name with some customization
56///
57/// # Examples
58///
59/// ```
60/// use anarchist_readable_name_generator_lib::readable_name_custom;
61/// use rand::prelude::*;
62/// use rand_chacha::ChaChaRng;
63///
64/// let rng = ChaChaRng::seed_from_u64(2);
65/// assert_eq!(
66/// readable_name_custom("+", rng),
67/// "romantic+kamalmaz"
68/// );
69/// ```
70///
71/// # Panics
72///
73/// Should not panic, would panic if there were no ADJECTIVES or if NAMES (both constants guaranteed not to be empty)
74#[must_use]
75pub fn readable_name_custom<R: Rng>(seperator: &str, mut rng: R) -> String {
76 format!(
77 "{}{}{}",
78 ADJECTIVES
79 .choose(&mut rng)
80 .expect("This should never fail, our list is predefined"),
81 seperator,
82 NAMES
83 .choose(&mut rng)
84 .expect("This should never fail, our list is predefined")
85 )
86}
87
88/// Generate a readable name with some customization and a random numeric suffix
89///
90/// # Examples
91///
92/// ```
93/// use anarchist_readable_name_generator_lib::{readable_name_custom_suffix};
94/// use rand::prelude::*;
95/// use rand_chacha::ChaChaRng;
96///
97/// let rng = ChaChaRng::seed_from_u64(2);
98/// assert_eq!(
99/// readable_name_custom_suffix("+", rng),
100/// "dynamic+lepper3"
101/// );
102/// ```
103///
104/// # Panics
105///
106/// Should not panic, would panic if there were no ADJECTIVES or if NAMES (both constants guaranteed not to be empty)
107#[must_use]
108pub fn readable_name_custom_suffix<R: Rng>(seperator: &str, mut rng: R) -> String {
109 let suffix = rng.random_range(0..=9);
110
111 format!("{}{}", readable_name_custom(seperator, &mut rng), suffix)
112}
113
114/// Generate a readable name with some customization
115///
116/// # Examples
117///
118/// ```
119/// use anarchist_readable_name_generator_lib::readable_name;
120///
121/// assert!(readable_name().len() > 0)
122/// ```
123#[must_use]
124pub fn readable_name() -> String {
125 let rng = rand::rng();
126 readable_name_custom("_", rng)
127}
128
129#[cfg(test)]
130mod test_readable_name_custom {
131 use super::{readable_name_custom, readable_name_custom_suffix};
132
133 use rand::prelude::*;
134 use rand_chacha::ChaChaRng;
135
136 #[test]
137 fn it_generates_a_name_with_a_custom_separator() {
138 let rng = rand::rng();
139 let split = readable_name_custom("-", rng)
140 .split('-')
141 .map(String::from)
142 .collect::<Vec<_>>();
143 assert!(!split.first().unwrap().is_empty());
144 assert!(!split.get(1).unwrap().is_empty());
145 assert_eq!(split.len(), 2);
146 }
147
148 #[test]
149 fn it_can_be_made_predictable_with_a_known_seed() {
150 let rng_1 = ChaChaRng::seed_from_u64(2);
151 let rng_2 = ChaChaRng::seed_from_u64(2);
152 assert_eq!(
153 readable_name_custom("_", rng_1),
154 readable_name_custom("_", rng_2)
155 );
156 }
157
158 #[test]
159 fn it_can_add_a_random_number_to_the_end_to_make_it_unique() {
160 let rng_1 = ChaChaRng::seed_from_u64(2);
161 assert_eq!(readable_name_custom_suffix("_", rng_1), "dynamic_lepper3");
162 }
163}
164
165#[cfg(doctest)]
166mod test_readme {
167 macro_rules! external_doc_test {
168 ($x:expr) => {
169 #[doc = $x]
170 unsafe extern "C" {}
171 };
172 }
173
174 external_doc_test!(include_str!("../README.md"));
175}