litex/runtime/
runtime_generate_unused_names.rs1use crate::prelude::*;
2use std::collections::HashSet;
3use std::time::{SystemTime, UNIX_EPOCH};
4
5impl Runtime {
6 fn generated_name_is_available_with_reserved(
7 &self,
8 candidate_name: &str,
9 reserved_names: &HashSet<String>,
10 ) -> bool {
11 if is_valid_litex_name(candidate_name).is_err() {
12 return false;
13 }
14 if reserved_names.contains(candidate_name) {
15 return false;
16 }
17 true
18 }
19
20 pub fn generate_one_unused_name_with_reserved(
21 &self,
22 reserved_names: &HashSet<String>,
23 ) -> String {
24 for i in 1..=4096usize {
25 let candidate_name = format!("x{}", i);
26 if self.generated_name_is_available_with_reserved(&candidate_name, reserved_names) {
27 return candidate_name;
28 }
29 }
30
31 let available_chars: Vec<char> = "abcdefghijklmnopqrstuvwxyz".chars().collect();
32 let first_char_candidates: Vec<char> = "abcdefghijklmnopqrstuvwxyz".chars().collect();
33 let mut try_index: usize = 0;
34 loop {
35 let current_time_nanos: u128 = match SystemTime::now().duration_since(UNIX_EPOCH) {
36 Ok(current_duration) => current_duration.as_nanos(),
37 Err(_) => 0,
38 };
39 let mixed_seed_value: u128 =
40 current_time_nanos ^ ((try_index as u128 + 1) * 0x9e3779b97f4a7c15u128);
41 let generated_name_length: usize = 8 + (mixed_seed_value as usize % 17);
42
43 let mut generated_chars: Vec<char> = Vec::new();
44 let first_char_index = ((mixed_seed_value >> 1) as usize) % first_char_candidates.len();
45 generated_chars.push(first_char_candidates[first_char_index]);
46
47 let mut current_state_value: u128 = mixed_seed_value;
48 for character_index in 1..generated_name_length {
49 current_state_value = current_state_value
50 .wrapping_mul(6364136223846793005u128)
51 .wrapping_add(1442695040888963407u128 + character_index as u128);
52 let available_char_index = (current_state_value as usize) % available_chars.len();
53 generated_chars.push(available_chars[available_char_index]);
54 }
55
56 let candidate_name: String = generated_chars.into_iter().collect();
57 if !self.generated_name_is_available_with_reserved(&candidate_name, reserved_names) {
58 try_index += 1;
59 continue;
60 }
61 return candidate_name;
62 }
63 }
64
65 pub fn generate_random_unused_names(&self, count: usize) -> Vec<String> {
66 let mut reserved_names: HashSet<String> = HashSet::with_capacity(count);
67 let mut generated_names: Vec<String> = Vec::with_capacity(count);
68 for _ in 0..count {
69 let generated_name = self.generate_one_unused_name_with_reserved(&reserved_names);
70 reserved_names.insert(generated_name.clone());
71 generated_names.push(generated_name);
72 }
73 generated_names
74 }
75
76 pub fn generate_random_unused_name(&self) -> String {
77 self.generate_one_unused_name_with_reserved(&HashSet::new())
78 }
79}