virtue_next/generate/
impl.rs1use super::FnBuilder;
2use super::GenConst;
3use super::Generator;
4use super::Parent;
5use super::StreamBuilder;
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 Impl<'a, P: Parent> {
15 parent: &'a mut P,
16 outer_attr: Vec<StreamBuilder>,
17 inner_attr: Vec<StreamBuilder>,
18 name: String,
19 consts: Vec<StreamBuilder>,
21 custom_generic_constraints: Option<GenericConstraints>,
22 fns: Vec<(StreamBuilder, StreamBuilder)>,
23}
24
25impl<'a, P: Parent> Impl<'a, P> {
26 pub(super) fn with_parent_name(parent: &'a mut P) -> Self {
27 Self {
28 outer_attr: Vec::new(),
29 inner_attr: Vec::new(),
30 name: parent.name().to_string(),
31 parent,
32 consts: Vec::new(),
33 custom_generic_constraints: None,
34 fns: Vec::new(),
35 }
36 }
37
38 pub(super) fn new(
39 parent: &'a mut P,
40 name: impl Into<String>,
41 ) -> Self {
42 Self {
43 outer_attr: Vec::new(),
44 inner_attr: Vec::new(),
45 parent,
46 name: name.into(),
47 consts: Vec::new(),
48 custom_generic_constraints: None,
49 fns: Vec::new(),
50 }
51 }
52
53 pub fn impl_outer_attr(
59 &mut self,
60 attr: impl AsRef<str>,
61 ) -> Result {
62 let mut builder = StreamBuilder::new();
63 builder.punct('#').group(Delimiter::Bracket, |builder| {
64 builder.push_parsed(attr)?;
65 Ok(())
66 })?;
67 self.outer_attr.push(builder);
68 Ok(())
69 }
70
71 pub fn impl_inner_attr(
77 &mut self,
78 attr: impl AsRef<str>,
79 ) -> Result {
80 let mut builder = StreamBuilder::new();
81 builder
82 .punct('#')
83 .punct('!')
84 .group(Delimiter::Brace, |builder| {
85 builder.push_parsed(attr)?;
86 Ok(())
87 })?;
88 self.inner_attr.push(builder);
89 Ok(())
90 }
91
92 pub fn generate_fn(
104 &mut self,
105 name: impl Into<String>,
106 ) -> FnBuilder<'_, Self> {
107 FnBuilder::new(self, name)
108 }
109
110 pub fn generate_const(
131 &mut self,
132 name: impl Into<String>,
133 ty: impl Into<String>,
134 ) -> GenConst<'_> {
135 GenConst::new(&mut self.consts, name, ty)
136 }
137}
138
139impl Impl<'_, Generator> {
140 pub fn modify_generic_constraints<CB>(
168 &mut self,
169 cb: CB,
170 ) -> &mut Self
171 where
172 CB: FnOnce(&Generics, &mut GenericConstraints),
173 {
174 if let Some(generics) = self.parent.generics() {
175 let constraints = self.custom_generic_constraints.get_or_insert_with(|| {
176 self.parent
177 .generic_constraints()
178 .cloned()
179 .unwrap_or_default()
180 });
181 cb(generics, constraints);
182 }
183 self
184 }
185}
186
187impl<P: Parent> FnParent for Impl<'_, P> {
188 fn append(
189 &mut self,
190 fn_definition: StreamBuilder,
191 fn_body: StreamBuilder,
192 ) -> Result {
193 self.fns.push((fn_definition, fn_body));
194 Ok(())
195 }
196}
197
198impl<P: Parent> Drop for Impl<'_, P> {
199 fn drop(&mut self) {
200 if std::thread::panicking() {
201 return;
202 }
203 let mut builder = StreamBuilder::new();
204 for attr in std::mem::take(&mut self.outer_attr) {
205 builder.append(attr);
206 }
207 builder.ident_str("impl");
208
209 if let Some(generics) = self.parent.generics() {
210 builder.append(generics.impl_generics());
211 }
212 builder.push_parsed(&self.name).unwrap();
213
214 if let Some(generics) = self.parent.generics() {
215 builder.append(generics.type_generics());
216 }
217 match self.custom_generic_constraints.take() {
218 | Some(generic_constraints) => {
219 builder.append(generic_constraints.where_clause());
220 },
221 | _ => {
222 if let Some(generic_constraints) = self.parent.generic_constraints() {
223 builder.append(generic_constraints.where_clause());
224 }
225 },
226 }
227
228 builder
229 .group(Delimiter::Brace, |builder| {
230 for attr in std::mem::take(&mut self.inner_attr) {
231 builder.append(attr);
232 }
233 for r#const in std::mem::take(&mut self.consts) {
234 builder.append(r#const);
235 }
236 for (fn_def, fn_body) in std::mem::take(&mut self.fns) {
237 builder.append(fn_def);
238 builder
239 .group(Delimiter::Brace, |body| {
240 *body = fn_body;
241 Ok(())
242 })
243 .unwrap();
244 }
245 Ok(())
246 })
247 .unwrap();
248
249 self.parent.append(builder);
250 }
251}