virtue_next/generate/
mod.rs1mod gen_enum;
16mod gen_struct;
17mod generate_item;
18mod generate_mod;
19mod generator;
20mod r#impl;
21mod impl_for;
22mod stream_builder;
23
24use crate::parse::Visibility;
25use crate::{
26 parse::{GenericConstraints, Generics},
27 prelude::{Delimiter, Ident, TokenStream},
28};
29use std::fmt;
30use std::marker::PhantomData;
31
32pub use self::gen_enum::GenEnum;
33pub use self::gen_struct::GenStruct;
34pub use self::generate_item::{FnBuilder, FnSelfArg, GenConst};
35pub use self::generate_mod::GenerateMod;
36pub use self::generator::Generator;
37pub use self::r#impl::Impl;
38pub use self::impl_for::ImplFor;
39pub use self::stream_builder::{PushParseError, StreamBuilder};
40
41#[allow(missing_docs)]
43pub trait Parent {
44 fn append(&mut self, builder: StreamBuilder);
45 fn name(&self) -> &Ident;
46 fn generics(&self) -> Option<&Generics>;
47 fn generic_constraints(&self) -> Option<&GenericConstraints>;
48}
49
50#[allow(missing_docs)]
52pub enum StringOrIdent {
53 String(String),
54 Ident(Ident),
57}
58
59impl fmt::Display for StringOrIdent {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 match self {
62 Self::String(s) => s.fmt(f),
63 Self::Ident(i) => i.fmt(f),
64 }
65 }
66}
67
68impl From<String> for StringOrIdent {
69 fn from(s: String) -> Self {
70 Self::String(s)
71 }
72}
73impl From<Ident> for StringOrIdent {
74 fn from(i: Ident) -> Self {
75 Self::Ident(i)
76 }
77}
78impl<'a> From<&'a str> for StringOrIdent {
79 fn from(s: &'a str) -> Self {
80 Self::String(s.to_owned())
81 }
82}
83
84pub struct Path(Vec<StringOrIdent>);
86
87impl From<String> for Path {
88 fn from(s: String) -> Self {
89 StringOrIdent::from(s).into()
90 }
91}
92
93impl From<Ident> for Path {
94 fn from(i: Ident) -> Self {
95 StringOrIdent::from(i).into()
96 }
97}
98
99impl From<&str> for Path {
100 fn from(s: &str) -> Self {
101 StringOrIdent::from(s).into()
102 }
103}
104
105impl From<StringOrIdent> for Path {
106 fn from(value: StringOrIdent) -> Self {
107 Self(vec![value])
108 }
109}
110
111impl FromIterator<String> for Path {
112 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
113 iter.into_iter().map(StringOrIdent::from).collect()
114 }
115}
116
117impl FromIterator<Ident> for Path {
118 fn from_iter<T: IntoIterator<Item = Ident>>(iter: T) -> Self {
119 iter.into_iter().map(StringOrIdent::from).collect()
120 }
121}
122
123impl<'a> FromIterator<&'a str> for Path {
124 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
125 iter.into_iter().map(StringOrIdent::from).collect()
126 }
127}
128
129impl FromIterator<StringOrIdent> for Path {
130 fn from_iter<T: IntoIterator<Item = StringOrIdent>>(iter: T) -> Self {
131 Self(iter.into_iter().collect())
132 }
133}
134
135impl IntoIterator for Path {
136 type Item = StringOrIdent;
137 type IntoIter = std::vec::IntoIter<StringOrIdent>;
138
139 fn into_iter(self) -> Self::IntoIter {
140 self.0.into_iter()
141 }
142}
143
144struct Field {
146 name: String,
147 vis: Visibility,
148 ty: String,
149 attributes: Vec<StreamBuilder>,
150}
151
152impl Field {
153 fn new(name: impl Into<String>, vis: Visibility, ty: impl Into<String>) -> Self {
154 Self {
155 name: name.into(),
156 vis,
157 ty: ty.into(),
158 attributes: Vec::new(),
159 }
160 }
161}
162
163pub struct FieldBuilder<'a, P> {
165 fields: &'a mut Vec<Field>,
166 _parent: PhantomData<P>, }
168
169impl<P> FieldBuilder<'_, P> {
170 pub fn with_attribute(
211 &mut self,
212 name: impl AsRef<str>,
213 value: impl FnOnce(&mut StreamBuilder) -> crate::Result,
214 ) -> crate::Result<&mut Self> {
215 self.current().with_attribute(name, value)?;
216 Ok(self)
217 }
218
219 pub fn with_parsed_attribute(
254 &mut self,
255 attribute: impl AsRef<str>,
256 ) -> crate::Result<&mut Self> {
257 self.current().with_parsed_attribute(attribute)?;
258 Ok(self)
259 }
260
261 pub fn with_attribute_stream(&mut self, attribute: impl Into<TokenStream>) -> &mut Self {
284 self.current().with_attribute_stream(attribute);
285 self
286 }
287
288 pub fn add_field(&mut self, name: impl Into<String>, ty: impl Into<String>) -> &mut Self {
309 self.fields.push(Field::new(name, Visibility::Default, ty));
310 self
311 }
312}
313
314impl<'a, P: Parent> FieldBuilder<'_, GenStruct<'a, P>> {
316 pub fn make_pub(&mut self) -> &mut Self {
318 self.current().vis = Visibility::Pub;
319 self
320 }
321}
322
323impl<'a, P> From<&'a mut Vec<Field>> for FieldBuilder<'a, P> {
324 fn from(fields: &'a mut Vec<Field>) -> Self {
325 Self {
326 fields,
327 _parent: PhantomData,
328 }
329 }
330}
331
332impl<P> FieldBuilder<'_, P> {
333 fn current(&mut self) -> &mut Field {
334 self.fields.last_mut().unwrap()
336 }
337}
338
339trait AttributeContainer {
341 fn derives(&mut self) -> &mut Vec<Path>;
342 fn attributes(&mut self) -> &mut Vec<StreamBuilder>;
343
344 fn with_derive(&mut self, derive: impl Into<Path>) -> &mut Self {
345 self.derives().push(derive.into());
346 self
347 }
348
349 fn with_derives<T: Into<Path>>(&mut self, derives: impl IntoIterator<Item = T>) -> &mut Self {
350 self.derives().extend(derives.into_iter().map(Into::into));
351 self
352 }
353
354 fn with_attribute(
355 &mut self,
356 name: impl AsRef<str>,
357 value: impl FnOnce(&mut StreamBuilder) -> crate::Result,
358 ) -> crate::Result<&mut Self> {
359 let mut stream = StreamBuilder::new();
360 value(stream.ident_str(name))?;
361 self.attributes().push(stream);
362 Ok(self)
363 }
364
365 fn with_parsed_attribute(&mut self, attribute: impl AsRef<str>) -> crate::Result<&mut Self> {
366 let mut stream = StreamBuilder::new();
367 stream.push_parsed(attribute)?;
368 self.attributes().push(stream);
369 Ok(self)
370 }
371
372 fn with_attribute_stream(&mut self, attribute: impl Into<TokenStream>) -> &mut Self {
373 let stream = StreamBuilder {
374 stream: attribute.into(),
375 };
376 self.attributes().push(stream);
377 self
378 }
379
380 fn build_derives(&mut self, b: &mut StreamBuilder) -> &mut Self {
381 let derives = std::mem::take(self.derives());
382 if !derives.is_empty() {
383 build_attribute(b, |b| {
384 b.ident_str("derive").group(Delimiter::Parenthesis, |b| {
385 for (idx, derive) in derives.into_iter().enumerate() {
386 if idx > 0 {
387 b.punct(',');
388 }
389 for (idx, component) in derive.into_iter().enumerate() {
390 if idx > 0 {
391 b.puncts("::");
392 }
393
394 match component {
395 StringOrIdent::String(s) => b.ident_str(s),
396 StringOrIdent::Ident(i) => b.ident(i),
397 };
398 }
399 }
400 Ok(())
401 })
402 })
403 .expect("could not build derives");
404 }
405 self
406 }
407
408 fn build_attributes(&mut self, b: &mut StreamBuilder) -> &mut Self {
409 for attr in std::mem::take(self.attributes()) {
410 build_attribute(b, |b| Ok(b.extend(attr.stream))).expect("could not build attribute");
411 }
412 self
413 }
414}
415
416impl AttributeContainer for Field {
417 fn derives(&mut self) -> &mut Vec<Path> {
418 unreachable!("fields cannot have derives")
419 }
420
421 fn attributes(&mut self) -> &mut Vec<StreamBuilder> {
422 &mut self.attributes
423 }
424}
425
426fn build_attribute<T>(b: &mut StreamBuilder, build: T) -> crate::Result
427where
428 T: FnOnce(&mut StreamBuilder) -> crate::Result<&mut StreamBuilder>,
429{
430 b.punct('#').group(Delimiter::Bracket, |b| {
431 build(b)?;
432 Ok(())
433 })?;
434
435 Ok(())
436}