iota_keys/
random_names.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5//! This library provides two functions to generate a random combination of an
6//! adjective and a precious stone name as a well formatted string, or a list of
7//! these strings.
8
9use std::collections::HashSet;
10
11use rand::{Rng, rngs::ThreadRng, thread_rng};
12
13/// A list of adjectives
14const LEFT_NAMES: [&str; 108] = [
15    "admiring",
16    "adoring",
17    "affectionate",
18    "agitated",
19    "amazing",
20    "angry",
21    "awesome",
22    "beautiful",
23    "blissful",
24    "bold",
25    "boring",
26    "brave",
27    "busy",
28    "charming",
29    "clever",
30    "compassionate",
31    "competent",
32    "condescending",
33    "confident",
34    "cool",
35    "cranky",
36    "crazy",
37    "dazzling",
38    "determined",
39    "distracted",
40    "dreamy",
41    "eager",
42    "ecstatic",
43    "elastic",
44    "elated",
45    "elegant",
46    "eloquent",
47    "epic",
48    "exciting",
49    "fervent",
50    "festive",
51    "flamboyant",
52    "focused",
53    "friendly",
54    "frosty",
55    "funny",
56    "gallant",
57    "gifted",
58    "goofy",
59    "gracious",
60    "great",
61    "happy",
62    "hardcore",
63    "heuristic",
64    "hopeful",
65    "hungry",
66    "infallible",
67    "inspiring",
68    "intelligent",
69    "interesting",
70    "jolly",
71    "jovial",
72    "keen",
73    "kind",
74    "laughing",
75    "loving",
76    "lucid",
77    "magical",
78    "modest",
79    "musing",
80    "mystifying",
81    "naughty",
82    "nervous",
83    "nice",
84    "nifty",
85    "nostalgic",
86    "objective",
87    "optimistic",
88    "peaceful",
89    "pedantic",
90    "pensive",
91    "practical",
92    "priceless",
93    "quirky",
94    "quizzical",
95    "recursing",
96    "relaxed",
97    "reverent",
98    "romantic",
99    "sad",
100    "serene",
101    "sharp",
102    "silly",
103    "sleepy",
104    "stoic",
105    "strange",
106    "stupefied",
107    "suspicious",
108    "sweet",
109    "tender",
110    "thirsty",
111    "trusting",
112    "unruffled",
113    "upbeat",
114    "vibrant",
115    "vigilant",
116    "vigorous",
117    "wizardly",
118    "wonderful",
119    "xenodochial",
120    "youthful",
121    "zealous",
122    "zen",
123];
124
125const LEFT_LENGTH: usize = LEFT_NAMES.len();
126
127/// A list of precious stones
128const RIGHT_NAMES: [&str; 53] = [
129    "agates",
130    "alexandrite",
131    "amber",
132    "amethyst",
133    "apatite",
134    "avanturine",
135    "axinite",
136    "beryl",
137    "beryl",
138    "carnelian",
139    "chalcedony",
140    "chrysoberyl",
141    "chrysolite",
142    "chrysoprase",
143    "coral",
144    "corundum",
145    "crocidolite",
146    "cyanite",
147    "cymophane",
148    "diamond",
149    "dichroite",
150    "emerald",
151    "epidote",
152    "euclase",
153    "felspar",
154    "garnet",
155    "heliotrope",
156    "hematite",
157    "hiddenite",
158    "hypersthene",
159    "idocrase",
160    "jasper",
161    "jet",
162    "labradorite",
163    "malachite",
164    "moonstone",
165    "obsidian",
166    "opal",
167    "pearl",
168    "phenacite",
169    "plasma",
170    "prase",
171    "quartz",
172    "ruby",
173    "sapphire",
174    "sphene",
175    "spinel",
176    "spodumene",
177    "sunstone",
178    "topaz",
179    "tourmaline",
180    "turquois",
181    "zircon",
182];
183const RIGHT_LENGTH: usize = RIGHT_NAMES.len();
184
185/// Return a random name formatted as first-second from a list of strings.
186///
187/// The main purpose of this function is to generate random aliases for
188/// addresses.
189pub fn random_name(conflicts: &HashSet<String>) -> String {
190    let mut rng = thread_rng();
191    // as long as the generated name is in the list of conflicts,
192    // we try to find a different name that is not in the list yet
193    loop {
194        let output = generate(&mut rng);
195        if !conflicts.contains(&output) {
196            return output;
197        }
198    }
199}
200
201/// Return a unique collection of names.
202pub fn random_names(mut conflicts: HashSet<String>, output_size: usize) -> Vec<String> {
203    let mut names = Vec::with_capacity(output_size);
204    names.resize_with(output_size, || {
205        let name = random_name(&conflicts);
206        conflicts.insert(name.clone());
207        name
208    });
209    names
210}
211
212// Generate a random name as a pair from left and right string arrays
213fn generate(rng: &mut ThreadRng) -> String {
214    let left_idx = rng.gen_range(0..LEFT_LENGTH);
215    let right_idx = rng.gen_range(0..RIGHT_LENGTH);
216    format!(
217        "{}-{}",
218        LEFT_NAMES.get(left_idx).unwrap(),
219        RIGHT_NAMES.get(right_idx).unwrap()
220    )
221}