virtue_next/generate/
impl.rs1use super::{FnBuilder, GenConst, Generator, Parent, StreamBuilder, generate_item::FnParent};
2use crate::{
3 parse::{GenericConstraints, Generics},
4 prelude::{Delimiter, Result},
5};
6
7#[must_use]
8pub struct Impl<'a, P: Parent> {
10 parent: &'a mut P,
11 outer_attr: Vec<StreamBuilder>,
12 inner_attr: Vec<StreamBuilder>,
13 name: String,
14 consts: Vec<StreamBuilder>,
16 custom_generic_constraints: Option<GenericConstraints>,
17 fns: Vec<(StreamBuilder, StreamBuilder)>,
18}
19
20impl<'a, P: Parent> Impl<'a, P> {
21 pub(super) fn with_parent_name(parent: &'a mut P) -> Self {
22 Self {
23 outer_attr: Vec::new(),
24 inner_attr: Vec::new(),
25 name: parent.name().to_string(),
26 parent,
27 consts: Vec::new(),
28 custom_generic_constraints: None,
29 fns: Vec::new(),
30 }
31 }
32
33 pub(super) fn new(parent: &'a mut P, name: impl Into<String>) -> Self {
34 Self {
35 outer_attr: Vec::new(),
36 inner_attr: Vec::new(),
37 parent,
38 name: name.into(),
39 consts: Vec::new(),
40 custom_generic_constraints: None,
41 fns: Vec::new(),
42 }
43 }
44
45 pub fn impl_outer_attr(&mut self, attr: impl AsRef<str>) -> Result {
47 let mut builder = StreamBuilder::new();
48 builder.punct('#').group(Delimiter::Bracket, |builder| {
49 builder.push_parsed(attr)?;
50 Ok(())
51 })?;
52 self.outer_attr.push(builder);
53 Ok(())
54 }
55
56 pub fn impl_inner_attr(&mut self, attr: impl AsRef<str>) -> Result {
58 let mut builder = StreamBuilder::new();
59 builder
60 .punct('#')
61 .punct('!')
62 .group(Delimiter::Brace, |builder| {
63 builder.push_parsed(attr)?;
64 Ok(())
65 })?;
66 self.inner_attr.push(builder);
67 Ok(())
68 }
69
70 pub fn generate_fn(&mut self, name: impl Into<String>) -> FnBuilder<'_, Self> {
82 FnBuilder::new(self, name)
83 }
84
85 pub fn generate_const(
105 &mut self,
106 name: impl Into<String>,
107 ty: impl Into<String>,
108 ) -> GenConst<'_> {
109 GenConst::new(&mut self.consts, name, ty)
110 }
111}
112
113impl<'a> Impl<'a, Generator> {
114 pub fn modify_generic_constraints<CB>(&mut self, cb: CB) -> &mut Self
142 where
143 CB: FnOnce(&Generics, &mut GenericConstraints),
144 {
145 if let Some(generics) = self.parent.generics() {
146 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
147 self.parent
148 .generic_constraints()
149 .cloned()
150 .unwrap_or_default()
151 });
152 cb(generics, constraints);
153 }
154 self
155 }
156}
157
158impl<'a, P: Parent> FnParent for Impl<'a, P> {
159 fn append(&mut self, fn_definition: StreamBuilder, fn_body: StreamBuilder) -> Result {
160 self.fns.push((fn_definition, fn_body));
161 Ok(())
162 }
163}
164
165impl<'a, P: Parent> Drop for Impl<'a, P> {
166 fn drop(&mut self) {
167 if std::thread::panicking() {
168 return;
169 }
170 let mut builder = StreamBuilder::new();
171 for attr in std::mem::take(&mut self.outer_attr) {
172 builder.append(attr);
173 }
174 builder.ident_str("impl");
175
176 if let Some(generics) = self.parent.generics() {
177 builder.append(generics.impl_generics());
178 }
179 builder.push_parsed(&self.name).unwrap();
180
181 if let Some(generics) = self.parent.generics() {
182 builder.append(generics.type_generics());
183 }
184 match self.custom_generic_constraints.take() {
185 Some(generic_constraints) => {
186 builder.append(generic_constraints.where_clause());
187 }
188 _ => {
189 if let Some(generic_constraints) = self.parent.generic_constraints() {
190 builder.append(generic_constraints.where_clause());
191 }
192 }
193 }
194
195 builder
196 .group(Delimiter::Brace, |builder| {
197 for attr in std::mem::take(&mut self.inner_attr) {
198 builder.append(attr);
199 }
200 for r#const in std::mem::take(&mut self.consts) {
201 builder.append(r#const);
202 }
203 for (fn_def, fn_body) in std::mem::take(&mut self.fns) {
204 builder.append(fn_def);
205 builder
206 .group(Delimiter::Brace, |body| {
207 *body = fn_body;
208 Ok(())
209 })
210 .unwrap();
211 }
212 Ok(())
213 })
214 .unwrap();
215
216 self.parent.append(builder);
217 }
218}