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) {
41 if !import.contains("::") && !import.contains('*') && !import.contains('{') {
44 return;
45 }
46 if !self.imports.iter().any(|i| i == import) {
47 self.imports.push(import.to_string());
48 }
49 }
50
51 pub fn add_item(&mut self, item: &str) {
53 self.items.push(item.to_string());
54 }
55
56 pub fn build(&self) -> String {
58 let mut capacity = 256; if let Some(header) = &self.doc_header {
60 capacity += header.len() + 1;
61 }
62 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);
66
67 if let Some(header) = &self.doc_header {
68 out.push_str(header);
69 out.push('\n');
70 }
71
72 if !self.imports.is_empty() {
73 for import in &self.imports {
74 writeln!(out, "use {import};").ok();
75 }
76 out.push('\n');
77 }
78
79 for (i, item) in self.items.iter().enumerate() {
80 out.push_str(item);
81 if i < self.items.len() - 1 {
82 out.push_str("\n\n");
83 }
84 }
85
86 if !out.ends_with('\n') {
87 out.push('\n');
88 }
89
90 out
91 }
92}
93
94pub struct StructBuilder {
96 attrs: Vec<String>,
97 visibility: String,
98 name: String,
99 derives: Vec<String>,
100 fields: Vec<(String, String, Vec<String>, String)>, }
102
103impl StructBuilder {
104 pub fn new(name: &str) -> Self {
105 Self {
106 attrs: vec![],
107 visibility: String::from("pub"),
108 name: name.to_string(),
109 derives: vec![],
110 fields: vec![],
111 }
112 }
113
114 pub fn add_attr(&mut self, attr: &str) -> &mut Self {
115 self.attrs.push(attr.to_string());
116 self
117 }
118
119 pub fn add_derive(&mut self, derive: &str) -> &mut Self {
120 self.derives.push(derive.to_string());
121 self
122 }
123
124 pub fn add_field(&mut self, name: &str, ty: &str, attrs: Vec<String>) -> &mut Self {
125 self.add_field_with_doc(name, ty, attrs, "")
126 }
127
128 pub fn add_field_with_doc(&mut self, name: &str, ty: &str, attrs: Vec<String>, doc: &str) -> &mut Self {
129 self.fields
130 .push((name.to_string(), ty.to_string(), attrs, doc.to_string()));
131 self
132 }
133
134 pub fn build(&self) -> String {
135 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
140 .fields
141 .iter()
142 .map(|(n, t, attrs, doc)| {
143 n.len() + t.len() + 12 + doc.len() + 8 + attrs.iter().map(|a| a.len() + 5).sum::<usize>()
144 })
145 .sum::<usize>();
146
147 let mut out = String::with_capacity(capacity);
148
149 if !self.derives.is_empty() {
150 writeln!(out, "#[derive({})]", self.derives.join(", ")).ok();
151 }
152
153 for attr in &self.attrs {
154 writeln!(out, "#[{attr}]").ok();
155 }
156
157 writeln!(out, "{} struct {} {{", self.visibility, self.name).ok();
158
159 for (name, ty, attrs, doc) in &self.fields {
160 if !doc.is_empty() {
161 for line in doc.lines() {
162 writeln!(out, " /// {line}").ok();
163 }
164 }
165 for attr in attrs {
166 writeln!(out, " #[{attr}]").ok();
167 }
168 writeln!(out, " pub {name}: {ty},").ok();
169 }
170
171 write!(out, "}}").ok();
172 out
173 }
174}
175
176pub struct ImplBuilder {
178 target: String,
179 attrs: Vec<String>,
180 methods: Vec<String>,
181}
182
183impl ImplBuilder {
184 pub fn new(target: &str) -> Self {
185 Self {
186 target: target.to_string(),
187 attrs: vec![],
188 methods: vec![],
189 }
190 }
191
192 pub fn add_attr(&mut self, attr: &str) -> &mut Self {
193 self.attrs.push(attr.to_string());
194 self
195 }
196
197 pub fn add_method(&mut self, method: &str) -> &mut Self {
198 self.methods.push(method.to_string());
199 self
200 }
201
202 pub fn build(&self) -> String {
203 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);
209
210 for attr in &self.attrs {
211 writeln!(out, "#[{attr}]").ok();
212 }
213
214 writeln!(out, "impl {} {{", self.target).ok();
215
216 for (i, method) in self.methods.iter().enumerate() {
217 for line in method.lines() {
219 if line.is_empty() {
220 out.push('\n');
221 } else {
222 writeln!(out, " {line}").ok();
223 }
224 }
225 if i < self.methods.len() - 1 {
226 out.push('\n');
227 }
228 }
229
230 write!(out, "}}").ok();
231 out
232 }
233}