1use alloc::{
2 format,
3 string::{String, ToString},
4 vec,
5 vec::Vec,
6};
7use core::{convert::TryFrom, iter::Cycle, ops::RangeInclusive};
8use proc_macro2::Span;
9use syn::{parse_quote, GenericParam, Generics, Ident, Lifetime, LifetimeDef, TypeParam};
10
11pub struct LetterGenerator(Vec<(char, Cycle<RangeInclusive<char>>)>);
12
13impl LetterGenerator {
14 fn new() -> Self {
15 Self(vec![Self::new_item()])
16 }
17
18 fn new_item() -> (char, Cycle<RangeInclusive<char>>) {
19 let mut cycle = ('a'..='z').cycle();
20 cycle.next();
21 ('a', cycle)
22 }
23
24 fn get_current_string(&self) -> String {
25 self.0.iter().map(|(c, _)| *c).collect()
26 }
27
28 fn inc_combo(&mut self, idx: usize) {
29 let value = self.0.get_mut(idx).unwrap();
30 let next = value.1.next().unwrap();
31 value.0 = next;
32 if next == 'a' {
33 if idx == 0 {
34 self.0.push(Self::new_item());
35 } else {
36 self.inc_combo(idx - 1);
37 }
38 }
39 }
40}
41
42impl Iterator for LetterGenerator {
43 type Item = String;
44
45 fn next(&mut self) -> Option<Self::Item> {
46 let rval = self.get_current_string();
47 self.inc_combo(self.0.len() - 1);
48 Some(rval)
49 }
50}
51
52impl Default for LetterGenerator {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58pub fn create_new_type_generics<const N: usize>(base: &Generics) -> ([Ident; N], Generics) {
59 let mut seen = Vec::new();
60 let mut insert_at = None;
61 for (i, param) in base.params.iter().enumerate() {
62 match ¶m {
63 GenericParam::Lifetime(_) => continue,
64 GenericParam::Type(TypeParam { ident, .. }) => {
65 if insert_at.is_none() {
66 insert_at = Some(i)
67 }
68 seen.push(ident.to_string())
69 }
70 _ => {
71 if insert_at.is_none() {
72 insert_at = Some(i)
73 }
74 break;
75 }
76 }
77 }
78 let mut new_types = Vec::with_capacity(N);
79 let mut type_gen = LetterGenerator::new().map(|l| format!("'{}", l));
80 while new_types.len() < N {
81 let name = type_gen.next().unwrap();
82 if !seen.contains(&name) {
83 let ty: TypeParam = parse_quote! { #name };
84 new_types.push(ty);
85 }
86 }
87 let insert_at = insert_at.unwrap_or(0);
88 let mut generics = base.clone();
89 for ty in new_types.iter() {
90 generics
91 .params
92 .insert(insert_at, GenericParam::Type(ty.clone()));
93 }
94 let type_idents = new_types
95 .into_iter()
96 .map(|tp| tp.ident)
97 .collect::<Vec<Ident>>();
98 if let Ok(ty) = <[Ident; N]>::try_from(type_idents) {
99 (ty, generics)
100 } else {
101 unreachable!()
102 }
103}
104
105pub fn create_new_lifetimes<const N: usize>(base: &Generics) -> ([Lifetime; N], Generics) {
111 let mut seen_lifetimes = Vec::new();
112 let mut insert_at = 0;
113 for (i, param) in base.params.iter().enumerate() {
114 if let GenericParam::Lifetime(lifetime) = ¶m {
115 seen_lifetimes.push(lifetime.lifetime.ident.to_string());
116 } else {
117 insert_at = i;
118 break;
119 }
120 }
121 let mut new_lifetimes = Vec::with_capacity(N);
122 let mut lifetime_gen = LetterGenerator::new().map(|l| format!("'{}", l));
123 while new_lifetimes.len() < N {
124 let lf_name = lifetime_gen.next().unwrap();
125 if !seen_lifetimes.contains(&lf_name) {
126 let lifetime = Lifetime::new(&lf_name, Span::call_site());
127 new_lifetimes.push(lifetime);
128 }
129 }
130 let mut generics = base.clone();
131 for lf in new_lifetimes.iter() {
132 let param = GenericParam::Lifetime(LifetimeDef::new(lf.clone()));
133 generics.params.insert(insert_at, param);
134 }
135 if let Ok(lifetimes) = <[Lifetime; N]>::try_from(new_lifetimes) {
136 (lifetimes, generics)
137 } else {
138 unreachable!()
139 }
140}
141
142#[cfg(test)]
143mod test {
144 use super::*;
145
146 #[test]
147 fn test_lifetime_generator() {
148 let mut gen = LetterGenerator::new();
149 for c in 'a'..='z' {
150 assert_eq!(gen.next().unwrap(), format!("'{}", c));
151 }
152 for c in 'a'..='z' {
153 assert_eq!(gen.next().unwrap(), format!("'a{}", c));
154 }
155 for c in 'a'..='z' {
156 assert_eq!(gen.next().unwrap(), format!("'b{}", c));
157 }
158 }
159}