1use std::fmt::Write;
2
3#[derive(Debug, Default)]
5pub struct RustFileBuilder {
6 doc_header: Option<String>,
7 imports: Vec<String>,
8 items: Vec<String>,
9}
10
11impl RustFileBuilder {
12 pub fn new() -> Self {
13 Self::default()
14 }
15
16 pub fn with_generated_header(mut self) -> Self {
18 self.doc_header = Some(
19 "// This file is auto-generated by alef. DO NOT EDIT.\n\
20 // Re-generate with: alef generate\n"
21 .to_string(),
22 );
23 self
24 }
25
26 pub fn add_inner_attribute(&mut self, attr: &str) {
29 if let Some(ref mut header) = self.doc_header {
31 header.push_str(&format!("#![{attr}]\n"));
32 } else {
33 self.doc_header = Some(format!("#![{attr}]\n"));
34 }
35 }
36
37 pub fn add_import(&mut self, import: &str) {
39 if !self.imports.iter().any(|i| i == import) {
40 self.imports.push(import.to_string());
41 }
42 }
43
44 pub fn add_item(&mut self, item: &str) {
46 self.items.push(item.to_string());
47 }
48
49 pub fn build(&self) -> String {
51 let mut capacity = 256; if let Some(header) = &self.doc_header {
53 capacity += header.len() + 1;
54 }
55 capacity += self.imports.iter().map(|i| i.len() + 6).sum::<usize>(); capacity += self.items.iter().map(|i| i.len() + 2).sum::<usize>(); let mut out = String::with_capacity(capacity);
59
60 if let Some(header) = &self.doc_header {
61 out.push_str(header);
62 out.push('\n');
63 }
64
65 if !self.imports.is_empty() {
66 for import in &self.imports {
67 writeln!(out, "use {import};").ok();
68 }
69 out.push('\n');
70 }
71
72 for (i, item) in self.items.iter().enumerate() {
73 out.push_str(item);
74 if i < self.items.len() - 1 {
75 out.push_str("\n\n");
76 }
77 }
78
79 if !out.ends_with('\n') {
80 out.push('\n');
81 }
82
83 out
84 }
85}
86
87pub struct StructBuilder {
89 attrs: Vec<String>,
90 visibility: String,
91 name: String,
92 derives: Vec<String>,
93 fields: Vec<(String, String, Vec<String>, String)>, }
95
96impl StructBuilder {
97 pub fn new(name: &str) -> Self {
98 Self {
99 attrs: vec![],
100 visibility: String::from("pub"),
101 name: name.to_string(),
102 derives: vec![],
103 fields: vec![],
104 }
105 }
106
107 pub fn add_attr(&mut self, attr: &str) -> &mut Self {
108 self.attrs.push(attr.to_string());
109 self
110 }
111
112 pub fn add_derive(&mut self, derive: &str) -> &mut Self {
113 self.derives.push(derive.to_string());
114 self
115 }
116
117 pub fn add_field(&mut self, name: &str, ty: &str, attrs: Vec<String>) -> &mut Self {
118 self.add_field_with_doc(name, ty, attrs, "")
119 }
120
121 pub fn add_field_with_doc(&mut self, name: &str, ty: &str, attrs: Vec<String>, doc: &str) -> &mut Self {
122 self.fields
123 .push((name.to_string(), ty.to_string(), attrs, doc.to_string()));
124 self
125 }
126
127 pub fn build(&self) -> String {
128 let mut capacity = 128; capacity += self.derives.iter().map(|d| d.len() + 2).sum::<usize>(); capacity += self.attrs.iter().map(|a| a.len() + 5).sum::<usize>(); capacity += self.name.len() + self.visibility.len() + 16; capacity += self
133 .fields
134 .iter()
135 .map(|(n, t, attrs, doc)| {
136 n.len() + t.len() + 12 + doc.len() + 8 + attrs.iter().map(|a| a.len() + 5).sum::<usize>()
137 })
138 .sum::<usize>();
139
140 let mut out = String::with_capacity(capacity);
141
142 if !self.derives.is_empty() {
143 writeln!(out, "#[derive({})]", self.derives.join(", ")).ok();
144 }
145
146 for attr in &self.attrs {
147 writeln!(out, "#[{attr}]").ok();
148 }
149
150 writeln!(out, "{} struct {} {{", self.visibility, self.name).ok();
151
152 for (name, ty, attrs, doc) in &self.fields {
153 if !doc.is_empty() {
154 for line in doc.lines() {
155 writeln!(out, " /// {line}").ok();
156 }
157 }
158 for attr in attrs {
159 writeln!(out, " #[{attr}]").ok();
160 }
161 writeln!(out, " pub {name}: {ty},").ok();
162 }
163
164 write!(out, "}}").ok();
165 out
166 }
167}
168
169pub struct ImplBuilder {
171 target: String,
172 attrs: Vec<String>,
173 methods: Vec<String>,
174}
175
176impl ImplBuilder {
177 pub fn new(target: &str) -> Self {
178 Self {
179 target: target.to_string(),
180 attrs: vec![],
181 methods: vec![],
182 }
183 }
184
185 pub fn add_attr(&mut self, attr: &str) -> &mut Self {
186 self.attrs.push(attr.to_string());
187 self
188 }
189
190 pub fn add_method(&mut self, method: &str) -> &mut Self {
191 self.methods.push(method.to_string());
192 self
193 }
194
195 pub fn build(&self) -> String {
196 let mut capacity = 128; capacity += self.target.len() + 10; capacity += self.attrs.iter().map(|a| a.len() + 5).sum::<usize>(); capacity += self.methods.iter().map(|m| m.len() + 4).sum::<usize>(); let mut out = String::with_capacity(capacity);
202
203 for attr in &self.attrs {
204 writeln!(out, "#[{attr}]").ok();
205 }
206
207 writeln!(out, "impl {} {{", self.target).ok();
208
209 for (i, method) in self.methods.iter().enumerate() {
210 for line in method.lines() {
212 if line.is_empty() {
213 out.push('\n');
214 } else {
215 writeln!(out, " {line}").ok();
216 }
217 }
218 if i < self.methods.len() - 1 {
219 out.push('\n');
220 }
221 }
222
223 write!(out, "}}").ok();
224 out
225 }
226}