cargo_wiki/generators/
generic_gen.rs1use crate::generators::type_gen::TypeGenerator;
2use anyhow::Result;
3use rustdoc_types::{
4 GenericArg, GenericArgs, GenericBound, GenericParamDef, GenericParamDefKind, Generics, Term,
5 TraitBoundModifier, WherePredicate,
6};
7
8pub struct GenericGenerator;
9
10impl GenericGenerator {
11 pub fn generate_generics(generics: &Generics) -> Result<(String, String)> {
12 let params = Self::generate_generic_params(&generics.params)?;
13 let mut where_predicates = String::new();
14
15 if generics.where_predicates.len() > 0 {
16 where_predicates.push_str("\nwhere\n\t");
17
18 for (i, where_pred) in generics.where_predicates.iter().enumerate() {
19 if i != 0 {
20 where_predicates.push_str(",\n\t");
21 }
22
23 match where_pred {
24 WherePredicate::BoundPredicate {
25 type_,
26 bounds,
27 generic_params,
28 } => {
29 let generic_params = Self::generate_generic_params(generic_params)?;
30
31 if !generic_params.is_empty() {
32 where_predicates.push_str("for");
33 where_predicates.push_str(&generic_params);
34 where_predicates.push_str(" ");
35 }
36 where_predicates.push_str(&TypeGenerator::type_to_string(type_));
37
38 if bounds.len() > 0 {
39 where_predicates.push_str(": ");
40
41 for (i, bound) in bounds.iter().enumerate() {
42 if i != 0 {
43 where_predicates.push_str(" + ");
44 }
45
46 where_predicates.push_str(&Self::generate_generic_bounds(bound)?)
47 }
48 }
49 }
50 WherePredicate::LifetimePredicate { lifetime, outlives } => {
51 where_predicates.push_str(lifetime);
52
53 if outlives.len() > 0 {
54 where_predicates.push_str(": ");
55
56 for (i, outlive) in outlives.iter().enumerate() {
57 if i != 0 {
58 where_predicates.push_str(" + ");
59 where_predicates.push_str(outlive);
60 }
61 }
62 }
63 }
64 WherePredicate::EqPredicate { lhs, rhs } => {
65 where_predicates.push_str(&TypeGenerator::type_to_string(lhs));
66 where_predicates.push_str(" = ");
67
68 let rhs = match rhs {
69 Term::Type(type_) => TypeGenerator::type_to_string(type_),
70 Term::Constant(constant) => unimplemented!(),
71 };
72
73 where_predicates.push_str(&rhs)
74 }
75 }
76 }
77 }
78
79 Ok((params, where_predicates))
80 }
81
82 pub fn generate_generic_params(generic_params: &Vec<GenericParamDef>) -> Result<String> {
83 let mut params = String::new();
84
85 if generic_params.len() > 0 {
86 params.push_str("<");
87 for (i, param_def) in generic_params.iter().enumerate() {
88 if i != 0 {
90 params.push_str(", ")
91 }
92
93 match ¶m_def.kind {
94 GenericParamDefKind::Lifetime { outlives } => {
95 params.push_str(¶m_def.name);
97
98 if outlives.len() > 0 {
99 params.push_str(": ");
100
101 for (x, other_name) in outlives.iter().enumerate() {
102 if x != 0 {
103 params.push_str(" + ");
105 params.push_str(&other_name);
106 }
107 }
108 }
109 }
110 GenericParamDefKind::Type {
111 bounds,
112 default,
113 is_synthetic,
114 } => {
115 params.push_str(¶m_def.name);
116 if bounds.len() > 0 {
117 params.push_str(": ");
118 for (i, bound) in bounds.iter().enumerate() {
119 if i != 0 {
120 params.push_str(" + ");
121 }
122 params.push_str(&Self::generate_generic_bounds(bound)?);
123 }
124 }
125
126 if let Some(default_type) = default {
127 params.push_str(" = ");
128 params.push_str(&TypeGenerator::type_to_string(default_type));
129 }
130 }
132 GenericParamDefKind::Const { type_, default } => {
133 params.push_str("const ");
134 params.push_str(¶m_def.name);
135
136 params.push_str(": ");
137 params.push_str(&TypeGenerator::type_to_string(type_));
138 if let Some(default) = default {
139 params.push_str(" = ");
140 params.push_str(default);
141 }
142 }
143 }
144 }
145 params.push_str(">");
146 }
147
148 Ok(params)
149 }
150
151 pub fn generate_generic_bounds(bound: &GenericBound) -> Result<String> {
152 let mut bound_string = String::new();
153 match bound {
154 GenericBound::TraitBound {
155 trait_,
156 generic_params,
157 modifier,
158 } => {
159 bound_string.push_str(match modifier {
160 TraitBoundModifier::None => "",
161 TraitBoundModifier::Maybe => "?",
162 TraitBoundModifier::MaybeConst => "const? ",
164 });
165
166 let param = Self::generate_generic_params(generic_params)?;
167 if !param.is_empty() {
168 bound_string.push_str("for");
169 bound_string.push_str(¶m);
170 bound_string.push_str(" ");
171 }
172
173 bound_string.push_str(&TypeGenerator::path_to_string(&trait_));
174 }
175 GenericBound::Outlives(lifetime) => {
176 bound_string.push_str(lifetime);
177 }
178 GenericBound::Use(uses) => {
179 bound_string.push_str("use<");
180 for (i, use_) in uses.iter().enumerate() {
181 if i != 0 {
182 bound_string.push_str(", ");
183 }
184 bound_string.push_str(use_);
185 }
186 bound_string.push_str(">");
187 }
188 }
189 Ok(bound_string)
190 }
191
192 pub fn generate_generic_args(generic_args: &GenericArgs) -> String {
193 let mut generic_arg_string = String::new();
194
195 match generic_args {
196 GenericArgs::AngleBracketed { args, constraints } => {
197 if args.len() > 0 {
198 generic_arg_string.push_str("<");
199
200 for (i, arg) in args.iter().enumerate() {
201 if i != 0 {
202 generic_arg_string.push_str(", ");
203 }
204
205 match arg {
206 GenericArg::Lifetime(lifetime) => generic_arg_string.push_str(lifetime),
207 GenericArg::Type(type_) => {
208 generic_arg_string.push_str(&TypeGenerator::type_to_string(type_))
209 }
210 GenericArg::Const(constant) => {
212 generic_arg_string.push_str(&format!("{{ {} }}", constant.expr))
213 }
214 GenericArg::Infer => generic_arg_string.push_str("_"),
215 }
216
217 }
219
220 generic_arg_string.push_str(">");
221 }
222 }
223 GenericArgs::Parenthesized { inputs, output } => {
224 generic_arg_string.push_str("Fn(");
225
226 for (i, input) in inputs.iter().enumerate() {
227 if i != 0 {
228 generic_arg_string.push_str(", ");
229 }
230 generic_arg_string.push_str(&TypeGenerator::type_to_string(input));
231 }
232
233 generic_arg_string.push_str(")");
234
235 if let Some(type_) = output {
236 generic_arg_string.push_str(" -> ");
237 generic_arg_string.push_str(&TypeGenerator::type_to_string(type_));
238 }
239 }
240 }
241
242 generic_arg_string
243 }
244}