1use super::{generate_item::FnParent, FnBuilder, GenConst, Parent, StreamBuilder, StringOrIdent};
2use crate::{
3 parse::{GenericConstraints, Generics},
4 prelude::{Delimiter, Result},
5};
6
7#[must_use]
8pub struct ImplFor<'a, P: Parent> {
10 generator: &'a mut P,
11 outer_attr: Vec<StreamBuilder>,
12 inner_attr: Vec<StreamBuilder>,
13 type_name: StringOrIdent,
14 trait_name: Option<StringOrIdent>,
15 lifetimes: Option<Vec<String>>,
16 trait_generics: Option<Vec<String>>,
17 impl_generics: Vec<String>,
18 consts: Vec<StreamBuilder>,
19 custom_generic_constraints: Option<GenericConstraints>,
20 impl_types: Vec<StreamBuilder>,
21 fns: Vec<(StreamBuilder, StreamBuilder)>,
22}
23
24impl<'a, P: Parent> ImplFor<'a, P> {
25 pub(super) fn new(
26 generator: &'a mut P,
27 type_name: StringOrIdent,
28 trait_name: Option<StringOrIdent>,
29 ) -> Self {
30 Self {
31 generator,
32 outer_attr: Vec::new(),
33 inner_attr: Vec::new(),
34 trait_name,
35 type_name,
36 lifetimes: None,
37 trait_generics: None,
38 impl_generics: vec![],
39 consts: Vec::new(),
40 custom_generic_constraints: None,
41 impl_types: Vec::new(),
42 fns: Vec::new(),
43 }
44 }
45
46 pub(crate) fn with_lifetimes<ITER>(mut self, lifetimes: ITER) -> Self
48 where
49 ITER: IntoIterator,
50 ITER::Item: Into<String>,
51 {
52 self.lifetimes = Some(lifetimes.into_iter().map(Into::into).collect());
53 self
54 }
55
56 pub fn new_lifetimes_depend_on_existing(mut self) -> Self {
64 if let Some(new_lt) = &self.lifetimes {
65 if let Some(generics) = self.generator.generics() {
66 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
67 self.generator
68 .generic_constraints()
69 .cloned()
70 .unwrap_or_default()
71 });
72 for old_lt in generics.iter_lifetimes() {
73 for new_lt in new_lt {
74 constraints
75 .push_parsed_constraint(format!("'{}: '{}", new_lt, old_lt.ident))
76 .expect("Could not ensure new lifetimes depend on existing lifetimes");
77 }
78 }
79 }
80 }
81 self
82 }
83
84 pub fn with_trait_generics<ITER>(mut self, generics: ITER) -> Self
101 where
102 ITER: IntoIterator,
103 ITER::Item: Into<String>,
104 {
105 self.trait_generics = Some(generics.into_iter().map(Into::into).collect());
106 self
107 }
108
109 pub fn with_impl_generics<ITER>(mut self, generics: ITER) -> Self
124 where
125 ITER: IntoIterator,
126 ITER::Item: Into<String>,
127 {
128 self.impl_generics = generics.into_iter().map(Into::into).collect();
129 self
130 }
131
132 pub fn impl_outer_attr(&mut self, attr: impl AsRef<str>) -> Result {
134 let mut builder = StreamBuilder::new();
135 builder.punct('#').group(Delimiter::Bracket, |builder| {
136 builder.push_parsed(attr)?;
137 Ok(())
138 })?;
139 self.outer_attr.push(builder);
140 Ok(())
141 }
142
143 pub fn impl_inner_attr(&mut self, attr: impl AsRef<str>) -> Result {
145 let mut builder = StreamBuilder::new();
146 builder
147 .punct('#')
148 .punct('!')
149 .group(Delimiter::Brace, |builder| {
150 builder.push_parsed(attr)?;
151 Ok(())
152 })?;
153 self.inner_attr.push(builder);
154 Ok(())
155 }
156
157 pub fn generate_const(&mut self, name: impl Into<String>, ty: impl Into<String>) -> GenConst {
177 GenConst::new(&mut self.consts, name, ty)
178 }
179
180 pub fn generate_fn(&mut self, name: impl Into<String>) -> FnBuilder<ImplFor<'a, P>> {
192 FnBuilder::new(self, name)
193 }
194
195 pub fn impl_type(&mut self, name: impl AsRef<str>, value: impl AsRef<str>) -> Result {
205 let mut builder = StreamBuilder::new();
206 builder
207 .ident_str("type")
208 .push_parsed(name)?
209 .punct('=')
210 .push_parsed(value)?
211 .punct(';');
212 self.impl_types.push(builder);
213 Ok(())
214 }
215
216 pub fn modify_generic_constraints<CB>(&mut self, cb: CB) -> Result<&mut Self>
244 where
245 CB: FnOnce(&Generics, &mut GenericConstraints) -> Result,
246 {
247 if let Some(generics) = self.generator.generics() {
248 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
249 self.generator
250 .generic_constraints()
251 .cloned()
252 .unwrap_or_default()
253 });
254 cb(generics, constraints)?;
255 }
256 Ok(self)
257 }
258}
259
260impl<'a, P: Parent> FnParent for ImplFor<'a, P> {
261 fn append(&mut self, fn_definition: StreamBuilder, fn_body: StreamBuilder) -> Result {
262 self.fns.push((fn_definition, fn_body));
263 Ok(())
264 }
265}
266
267impl<P: Parent> Drop for ImplFor<'_, P> {
268 fn drop(&mut self) {
269 if std::thread::panicking() {
270 return;
271 }
272 let mut builder = StreamBuilder::new();
273 for attr in std::mem::take(&mut self.outer_attr) {
274 builder.append(attr);
275 }
276
277 self.generate_impl_definition(&mut builder);
278
279 builder
280 .group(Delimiter::Brace, |builder| {
281 for attr in std::mem::take(&mut self.inner_attr) {
282 builder.append(attr);
283 }
284 for ty in std::mem::take(&mut self.impl_types) {
285 builder.append(ty);
286 }
287 for r#const in std::mem::take(&mut self.consts) {
288 builder.append(r#const);
289 }
290 for (fn_def, fn_body) in std::mem::take(&mut self.fns) {
291 builder.append(fn_def);
292 builder
293 .group(Delimiter::Brace, |body| {
294 *body = fn_body;
295 Ok(())
296 })
297 .unwrap();
298 }
299 Ok(())
300 })
301 .unwrap();
302
303 self.generator.append(builder);
304 }
305}
306
307impl<P: Parent> ImplFor<'_, P> {
308 fn generate_impl_definition(&mut self, builder: &mut StreamBuilder) {
309 builder.ident_str("impl");
310
311 let impl_generics = self.impl_generics.as_slice();
312 if let Some(lifetimes) = &self.lifetimes {
313 if let Some(generics) = self.generator.generics() {
314 builder.append(generics.impl_generics_with_additional(lifetimes, impl_generics));
315 } else {
316 append_lifetimes_and_generics(builder, lifetimes, impl_generics);
317 }
318 } else if let Some(generics) = self.generator.generics() {
319 builder.append(generics.impl_generics_with_additional(&[], impl_generics));
320 } else if !impl_generics.is_empty() {
321 append_lifetimes_and_generics(builder, &[], impl_generics)
322 }
323 if let Some(t) = &self.trait_name {
324 builder.push_parsed(t.to_string()).unwrap();
325
326 let lifetimes = self.lifetimes.as_deref().unwrap_or_default();
327 let generics = self.trait_generics.as_deref().unwrap_or_default();
328 append_lifetimes_and_generics(builder, lifetimes, generics);
329 builder.ident_str("for");
330 }
331 builder.push_parsed(self.type_name.to_string()).unwrap();
332 if let Some(generics) = &self.generator.generics() {
333 builder.append(generics.type_generics());
334 }
335 if let Some(generic_constraints) = self.custom_generic_constraints.take() {
336 builder.append(generic_constraints.where_clause());
337 } else if let Some(generic_constraints) = &self.generator.generic_constraints() {
338 builder.append(generic_constraints.where_clause());
339 }
340 }
341}
342
343fn append_lifetimes_and_generics(
344 builder: &mut StreamBuilder,
345 lifetimes: &[String],
346 generics: &[String],
347) {
348 if lifetimes.is_empty() && generics.is_empty() {
349 return;
350 }
351
352 builder.punct('<');
353
354 for (idx, lt) in lifetimes.iter().enumerate() {
355 if idx > 0 {
356 builder.punct(',');
357 }
358 builder.lifetime_str(lt);
359 }
360
361 for (idx, gen) in generics.iter().enumerate() {
362 if idx > 0 || !lifetimes.is_empty() {
363 builder.punct(',');
364 }
365 builder.push_parsed(gen).unwrap();
366 }
367
368 builder.punct('>');
369}