1use super::{FnBuilder, GenConst, Parent, StreamBuilder, StringOrIdent, generate_item::FnParent};
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(
177 &mut self,
178 name: impl Into<String>,
179 ty: impl Into<String>,
180 ) -> GenConst<'_> {
181 GenConst::new(&mut self.consts, name, ty)
182 }
183
184 pub fn generate_fn(&mut self, name: impl Into<String>) -> FnBuilder<'_, ImplFor<'a, P>> {
196 FnBuilder::new(self, name)
197 }
198
199 pub fn impl_type(&mut self, name: impl AsRef<str>, value: impl AsRef<str>) -> Result {
209 let mut builder = StreamBuilder::new();
210 builder
211 .ident_str("type")
212 .push_parsed(name)?
213 .punct('=')
214 .push_parsed(value)?
215 .punct(';');
216 self.impl_types.push(builder);
217 Ok(())
218 }
219
220 pub fn modify_generic_constraints<CB>(&mut self, cb: CB) -> Result<&mut Self>
248 where
249 CB: FnOnce(&Generics, &mut GenericConstraints) -> Result,
250 {
251 if let Some(generics) = self.generator.generics() {
252 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
253 self.generator
254 .generic_constraints()
255 .cloned()
256 .unwrap_or_default()
257 });
258 cb(generics, constraints)?;
259 }
260 Ok(self)
261 }
262}
263
264impl<'a, P: Parent> FnParent for ImplFor<'a, P> {
265 fn append(&mut self, fn_definition: StreamBuilder, fn_body: StreamBuilder) -> Result {
266 self.fns.push((fn_definition, fn_body));
267 Ok(())
268 }
269}
270
271impl<P: Parent> Drop for ImplFor<'_, P> {
272 fn drop(&mut self) {
273 if std::thread::panicking() {
274 return;
275 }
276 let mut builder = StreamBuilder::new();
277 for attr in std::mem::take(&mut self.outer_attr) {
278 builder.append(attr);
279 }
280
281 self.generate_impl_definition(&mut builder);
282
283 builder
284 .group(Delimiter::Brace, |builder| {
285 for attr in std::mem::take(&mut self.inner_attr) {
286 builder.append(attr);
287 }
288 for ty in std::mem::take(&mut self.impl_types) {
289 builder.append(ty);
290 }
291 for r#const in std::mem::take(&mut self.consts) {
292 builder.append(r#const);
293 }
294 for (fn_def, fn_body) in std::mem::take(&mut self.fns) {
295 builder.append(fn_def);
296 builder
297 .group(Delimiter::Brace, |body| {
298 *body = fn_body;
299 Ok(())
300 })
301 .unwrap();
302 }
303 Ok(())
304 })
305 .unwrap();
306
307 self.generator.append(builder);
308 }
309}
310
311impl<P: Parent> ImplFor<'_, P> {
312 fn generate_impl_definition(&mut self, builder: &mut StreamBuilder) {
313 builder.ident_str("impl");
314
315 let impl_generics = self.impl_generics.as_slice();
316 if let Some(lifetimes) = &self.lifetimes {
317 if let Some(generics) = self.generator.generics() {
318 builder.append(generics.impl_generics_with_additional(lifetimes, impl_generics));
319 } else {
320 append_lifetimes_and_generics(builder, lifetimes, impl_generics);
321 }
322 } else if let Some(generics) = self.generator.generics() {
323 builder.append(generics.impl_generics_with_additional(&[], impl_generics));
324 } else if !impl_generics.is_empty() {
325 append_lifetimes_and_generics(builder, &[], impl_generics)
326 }
327 if let Some(t) = &self.trait_name {
328 builder.push_parsed(t.to_string()).unwrap();
329
330 let lifetimes = self.lifetimes.as_deref().unwrap_or_default();
331 let generics = self.trait_generics.as_deref().unwrap_or_default();
332 append_lifetimes_and_generics(builder, lifetimes, generics);
333 builder.ident_str("for");
334 }
335 builder.push_parsed(self.type_name.to_string()).unwrap();
336 if let Some(generics) = &self.generator.generics() {
337 builder.append(generics.type_generics());
338 }
339 match self.custom_generic_constraints.take() {
340 Some(generic_constraints) => {
341 builder.append(generic_constraints.where_clause());
342 }
343 _ => {
344 if let Some(generic_constraints) = &self.generator.generic_constraints() {
345 builder.append(generic_constraints.where_clause());
346 }
347 }
348 }
349 }
350}
351
352fn append_lifetimes_and_generics(
353 builder: &mut StreamBuilder,
354 lifetimes: &[String],
355 generics: &[String],
356) {
357 if lifetimes.is_empty() && generics.is_empty() {
358 return;
359 }
360
361 builder.punct('<');
362
363 for (idx, lt) in lifetimes.iter().enumerate() {
364 if idx > 0 {
365 builder.punct(',');
366 }
367 builder.lifetime_str(lt);
368 }
369
370 for (idx, r#gen) in generics.iter().enumerate() {
371 if idx > 0 || !lifetimes.is_empty() {
372 builder.punct(',');
373 }
374 builder.push_parsed(r#gen).unwrap();
375 }
376
377 builder.punct('>');
378}