1use super::FnBuilder;
2use super::GenConst;
3use super::Parent;
4use super::StreamBuilder;
5use super::StringOrIdent;
6use super::generate_item::FnParent;
7use crate::parse::GenericConstraints;
8use crate::parse::Generics;
9use crate::prelude::Delimiter;
10use crate::prelude::Result;
11
12#[must_use]
13pub struct ImplFor<'a, P: Parent> {
15 generator: &'a mut P,
16 outer_attr: Vec<StreamBuilder>,
17 inner_attr: Vec<StreamBuilder>,
18 type_name: StringOrIdent,
19 trait_name: Option<StringOrIdent>,
20 lifetimes: Option<Vec<String>>,
21 trait_generics: Option<Vec<String>>,
22 impl_generics: Vec<String>,
23 consts: Vec<StreamBuilder>,
24 custom_generic_constraints: Option<GenericConstraints>,
25 impl_types: Vec<StreamBuilder>,
26 fns: Vec<(StreamBuilder, StreamBuilder)>,
27 is_unsafe: bool,
28}
29
30impl<'a, P: Parent> ImplFor<'a, P> {
31 pub(super) const fn new(
32 generator: &'a mut P,
33 type_name: StringOrIdent,
34 trait_name: Option<StringOrIdent>,
35 ) -> Self {
36 Self {
37 generator,
38 outer_attr: Vec::new(),
39 inner_attr: Vec::new(),
40 trait_name,
41 type_name,
42 lifetimes: None,
43 trait_generics: None,
44 impl_generics: vec![],
45 consts: Vec::new(),
46 custom_generic_constraints: None,
47 impl_types: Vec::new(),
48 fns: Vec::new(),
49 is_unsafe: false,
50 }
51 }
52
53 pub(crate) fn with_lifetimes<ITER>(
55 mut self,
56 lifetimes: ITER,
57 ) -> Self
58 where
59 ITER: IntoIterator,
60 ITER::Item: Into<String>,
61 {
62 self.lifetimes = Some(lifetimes.into_iter().map(Into::into).collect());
63 self
64 }
65
66 pub fn new_lifetimes_depend_on_existing(mut self) -> Self {
78 if let Some(new_lt) = &self.lifetimes
79 && let Some(generics) = self.generator.generics()
80 {
81 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
82 self.generator
83 .generic_constraints()
84 .cloned()
85 .unwrap_or_default()
86 });
87 for old_lt in generics.iter_lifetimes() {
88 for new_lt in new_lt {
89 constraints
90 .push_parsed_constraint(format!("'{}: '{}", new_lt, old_lt.ident))
91 .expect("Could not ensure new lifetimes depend on existing lifetimes");
92 }
93 }
94 }
95 self
96 }
97
98 pub const fn make_unsafe(mut self) -> Self {
107 self.is_unsafe = true;
108 self
109 }
110
111 pub fn with_trait_generics<ITER>(
126 mut self,
127 generics: ITER,
128 ) -> Self
129 where
130 ITER: IntoIterator,
131 ITER::Item: Into<String>,
132 {
133 self.trait_generics = Some(generics.into_iter().map(Into::into).collect());
134 self
135 }
136
137 pub fn with_impl_generics<ITER>(
155 mut self,
156 generics: ITER,
157 ) -> Self
158 where
159 ITER: IntoIterator,
160 ITER::Item: Into<String>,
161 {
162 self.impl_generics = generics.into_iter().map(Into::into).collect();
163 self
164 }
165
166 pub fn impl_outer_attr(
172 &mut self,
173 attr: impl AsRef<str>,
174 ) -> Result {
175 let mut builder = StreamBuilder::new();
176 builder.punct('#').group(Delimiter::Bracket, |builder| {
177 builder.push_parsed(attr)?;
178 Ok(())
179 })?;
180 self.outer_attr.push(builder);
181 Ok(())
182 }
183
184 pub fn impl_inner_attr(
190 &mut self,
191 attr: impl AsRef<str>,
192 ) -> Result {
193 let mut builder = StreamBuilder::new();
194 builder
195 .punct('#')
196 .punct('!')
197 .group(Delimiter::Brace, |builder| {
198 builder.push_parsed(attr)?;
199 Ok(())
200 })?;
201 self.inner_attr.push(builder);
202 Ok(())
203 }
204
205 pub fn generate_const(
226 &mut self,
227 name: impl Into<String>,
228 ty: impl Into<String>,
229 ) -> GenConst<'_> {
230 GenConst::new(&mut self.consts, name, ty)
231 }
232
233 pub fn generate_fn(
249 &mut self,
250 name: impl Into<String>,
251 ) -> FnBuilder<'_, Self> {
252 FnBuilder::new(self, name)
253 }
254
255 pub fn impl_type(
269 &mut self,
270 name: impl AsRef<str>,
271 value: impl AsRef<str>,
272 ) -> Result {
273 let mut builder = StreamBuilder::new();
274 builder
275 .ident_str("type")
276 .push_parsed(name)?
277 .punct('=')
278 .push_parsed(value)?
279 .punct(';');
280 self.impl_types.push(builder);
281 Ok(())
282 }
283
284 pub fn modify_generic_constraints<CB>(
314 &mut self,
315 cb: CB,
316 ) -> Result<&mut Self>
317 where
318 CB: FnOnce(&Generics, &mut GenericConstraints) -> Result,
319 {
320 if let Some(generics) = self.generator.generics() {
321 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
322 self.generator
323 .generic_constraints()
324 .cloned()
325 .unwrap_or_default()
326 });
327 cb(generics, constraints)?;
328 }
329 Ok(self)
330 }
331}
332
333impl<P: Parent> FnParent for ImplFor<'_, P> {
334 fn append(
335 &mut self,
336 fn_definition: StreamBuilder,
337 fn_body: StreamBuilder,
338 ) -> Result {
339 self.fns.push((fn_definition, fn_body));
340 Ok(())
341 }
342}
343
344impl<P: Parent> Drop for ImplFor<'_, P> {
345 fn drop(&mut self) {
346 if std::thread::panicking() {
347 return;
348 }
349 let mut builder = StreamBuilder::new();
350 for attr in std::mem::take(&mut self.outer_attr) {
351 builder.append(attr);
352 }
353
354 self.generate_impl_definition(&mut builder);
355
356 builder
357 .group(Delimiter::Brace, |builder| {
358 for attr in std::mem::take(&mut self.inner_attr) {
359 builder.append(attr);
360 }
361 for ty in std::mem::take(&mut self.impl_types) {
362 builder.append(ty);
363 }
364 for r#const in std::mem::take(&mut self.consts) {
365 builder.append(r#const);
366 }
367 for (fn_def, fn_body) in std::mem::take(&mut self.fns) {
368 builder.append(fn_def);
369 builder
370 .group(Delimiter::Brace, |body| {
371 *body = fn_body;
372 Ok(())
373 })
374 .unwrap();
375 }
376 Ok(())
377 })
378 .unwrap();
379
380 self.generator.append(builder);
381 }
382}
383
384impl<P: Parent> ImplFor<'_, P> {
385 fn generate_impl_definition(
386 &mut self,
387 builder: &mut StreamBuilder,
388 ) {
389 if self.is_unsafe {
390 builder.ident_str("unsafe");
391 }
392 builder.ident_str("impl");
393
394 let impl_generics = self.impl_generics.as_slice();
395 if let Some(lifetimes) = &self.lifetimes {
396 if let Some(generics) = self.generator.generics() {
397 builder.append(generics.impl_generics_with_additional(lifetimes, impl_generics));
398 } else {
399 append_lifetimes_and_generics(builder, lifetimes, impl_generics);
400 }
401 } else if let Some(generics) = self.generator.generics() {
402 builder.append(generics.impl_generics_with_additional(&[], impl_generics));
403 } else if !impl_generics.is_empty() {
404 append_lifetimes_and_generics(builder, &[], impl_generics);
405 }
406 if let Some(t) = &self.trait_name {
407 builder.push_parsed(t.to_string()).unwrap();
408
409 let lifetimes = self.lifetimes.as_deref().unwrap_or_default();
410 let generics = self.trait_generics.as_deref().unwrap_or_default();
411 append_lifetimes_and_generics(builder, lifetimes, generics);
412 builder.ident_str("for");
413 }
414 builder.push_parsed(self.type_name.to_string()).unwrap();
415 if let Some(generics) = &self.generator.generics() {
416 builder.append(generics.type_generics());
417 }
418 match self.custom_generic_constraints.take() {
419 | Some(generic_constraints) => {
420 builder.append(generic_constraints.where_clause());
421 },
422 | _ => {
423 if let Some(generic_constraints) = &self.generator.generic_constraints() {
424 builder.append(generic_constraints.where_clause());
425 }
426 },
427 }
428 }
429}
430
431fn append_lifetimes_and_generics(
432 builder: &mut StreamBuilder,
433 lifetimes: &[String],
434 generics: &[String],
435) {
436 if lifetimes.is_empty() && generics.is_empty() {
437 return;
438 }
439
440 builder.punct('<');
441
442 for (idx, lt) in lifetimes.iter().enumerate() {
443 if idx > 0 {
444 builder.punct(',');
445 }
446 builder.lifetime_str(lt);
447 }
448
449 for (idx, r#gen) in generics.iter().enumerate() {
450 if idx > 0 || !lifetimes.is_empty() {
451 builder.punct(',');
452 }
453 builder.push_parsed(r#gen).unwrap();
454 }
455
456 builder.punct('>');
457}