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 if !self.derives.iter().any(|d| d == derive) {
121 self.derives.push(derive.to_string());
122 }
123 self
124 }
125
126 pub fn add_field(&mut self, name: &str, ty: &str, attrs: Vec<String>) -> &mut Self {
127 self.add_field_with_doc(name, ty, attrs, "")
128 }
129
130 pub fn add_field_with_doc(&mut self, name: &str, ty: &str, attrs: Vec<String>, doc: &str) -> &mut Self {
131 self.fields
132 .push((name.to_string(), ty.to_string(), attrs, doc.to_string()));
133 self
134 }
135
136 pub fn build(&self) -> String {
137 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
142 .fields
143 .iter()
144 .map(|(n, t, attrs, doc)| {
145 n.len() + t.len() + 12 + doc.len() + 8 + attrs.iter().map(|a| a.len() + 5).sum::<usize>()
146 })
147 .sum::<usize>();
148
149 let mut out = String::with_capacity(capacity);
150
151 if !self.derives.is_empty() {
152 writeln!(out, "#[derive({})]", self.derives.join(", ")).ok();
153 }
154
155 for attr in &self.attrs {
156 writeln!(out, "#[{attr}]").ok();
157 }
158
159 writeln!(out, "{} struct {} {{", self.visibility, self.name).ok();
160
161 for (name, ty, attrs, doc) in &self.fields {
162 if !doc.is_empty() {
163 for line in doc.lines() {
164 writeln!(out, " /// {line}").ok();
165 }
166 }
167 for attr in attrs {
168 writeln!(out, " #[{attr}]").ok();
169 }
170 writeln!(out, " pub {name}: {ty},").ok();
171 }
172
173 write!(out, "}}").ok();
174 out
175 }
176}
177
178pub struct ImplBuilder {
180 target: String,
181 attrs: Vec<String>,
182 methods: Vec<String>,
183}
184
185impl ImplBuilder {
186 pub fn new(target: &str) -> Self {
187 Self {
188 target: target.to_string(),
189 attrs: vec![],
190 methods: vec![],
191 }
192 }
193
194 pub fn add_attr(&mut self, attr: &str) -> &mut Self {
195 self.attrs.push(attr.to_string());
196 self
197 }
198
199 pub fn add_method(&mut self, method: &str) -> &mut Self {
200 self.methods.push(method.to_string());
201 self
202 }
203
204 pub fn build(&self) -> String {
205 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);
211
212 for attr in &self.attrs {
213 writeln!(out, "#[{attr}]").ok();
214 }
215
216 writeln!(out, "impl {} {{", self.target).ok();
217
218 for (i, method) in self.methods.iter().enumerate() {
219 for line in method.lines() {
221 if line.is_empty() {
222 out.push('\n');
223 } else {
224 writeln!(out, " {line}").ok();
225 }
226 }
227 if i < self.methods.len() - 1 {
228 out.push('\n');
229 }
230 }
231
232 write!(out, "}}").ok();
233 out
234 }
235}