1 | use super::*; |
2 | |
3 | // TODO: should we use rustfmt in the short term (with pre/post) |
4 | |
5 | #[derive (Default)] |
6 | pub struct Writer { |
7 | out: String, |
8 | indent: usize, |
9 | newline: bool, |
10 | } |
11 | |
12 | impl Writer { |
13 | pub fn new(file: &rdl::File) -> Self { |
14 | let mut writer = Self::default(); |
15 | writer.rdl_file(file); |
16 | writer |
17 | } |
18 | |
19 | pub fn into_string(mut self) -> String { |
20 | self.out.push(' \n' ); |
21 | self.out |
22 | } |
23 | |
24 | fn word(&mut self, value: &str) { |
25 | if self.newline { |
26 | self.newline = false; |
27 | self.out.push(' \n' ); |
28 | for _ in 0..self.indent { |
29 | self.out.push_str(" " ); |
30 | } |
31 | } |
32 | |
33 | self.out.push_str(value); |
34 | } |
35 | |
36 | fn newline(&mut self) { |
37 | self.newline = true; |
38 | } |
39 | |
40 | fn rdl_file(&mut self, file: &rdl::File) { |
41 | if file.winrt { |
42 | self.word("#![winrt] \n" ); |
43 | } else { |
44 | self.word("#![win32] \n" ); |
45 | } |
46 | |
47 | self.newline(); |
48 | |
49 | for reference in &file.references { |
50 | self.item_use(reference); |
51 | } |
52 | |
53 | for module in &file.modules { |
54 | self.rdl_module(module); |
55 | } |
56 | } |
57 | |
58 | fn rdl_module(&mut self, module: &rdl::Module) { |
59 | self.word("mod " ); |
60 | self.word(module.name()); |
61 | self.word(" {" ); |
62 | self.newline(); |
63 | self.indent += 1; |
64 | |
65 | for member in &module.members { |
66 | self.rdl_module_member(member); |
67 | self.newline(); |
68 | } |
69 | |
70 | self.indent -= 1; |
71 | self.newline(); |
72 | self.word("}" ); |
73 | self.newline(); |
74 | } |
75 | |
76 | fn rdl_module_member(&mut self, member: &rdl::ModuleMember) { |
77 | match member { |
78 | rdl::ModuleMember::Module(member) => self.rdl_module(member), |
79 | rdl::ModuleMember::Interface(member) => self.rdl_interface(member), |
80 | rdl::ModuleMember::Struct(member) => self.rdl_struct(member), |
81 | rdl::ModuleMember::Enum(member) => self.rdl_enum(member), |
82 | rdl::ModuleMember::Class(member) => self.rdl_class(member), |
83 | rdl::ModuleMember::Constant(member) => self.rdl_constant(member), |
84 | rdl::ModuleMember::Function(member) => self.rdl_function(member), |
85 | } |
86 | } |
87 | |
88 | fn rdl_class(&mut self, member: &rdl::Class) { |
89 | self.attrs(&member.attributes); |
90 | self.word("class " ); |
91 | self.word(&member.name); |
92 | |
93 | if !member.extends.is_empty() || member.base.is_some() { |
94 | self.word(" : " ); |
95 | |
96 | if let Some(path) = &member.base { |
97 | self.word("class " ); |
98 | self.type_path(path); |
99 | |
100 | if !member.extends.is_empty() { |
101 | self.word(", " ); |
102 | } |
103 | } |
104 | |
105 | let mut first = true; |
106 | for path in &member.extends { |
107 | if first { |
108 | first = false; |
109 | } else { |
110 | self.word(", " ); |
111 | } |
112 | self.type_path(path); |
113 | } |
114 | } |
115 | |
116 | self.word(";" ); |
117 | self.newline(); |
118 | } |
119 | |
120 | fn rdl_interface(&mut self, member: &rdl::Interface) { |
121 | self.attrs(&member.attributes); |
122 | self.word("interface " ); |
123 | self.word(&member.name); |
124 | |
125 | if !member.generics.is_empty() { |
126 | self.word("<" ); |
127 | |
128 | let mut first = true; |
129 | for generic in &member.generics { |
130 | if first { |
131 | first = false; |
132 | } else { |
133 | self.word(", " ); |
134 | } |
135 | self.word(generic); |
136 | } |
137 | |
138 | self.word(">" ); |
139 | } |
140 | |
141 | if !member.extends.is_empty() { |
142 | self.word(" : " ); |
143 | |
144 | let mut first = true; |
145 | for path in &member.extends { |
146 | if first { |
147 | first = false; |
148 | } else { |
149 | self.word(", " ); |
150 | } |
151 | self.type_path(path); |
152 | } |
153 | } |
154 | |
155 | self.word(" {" ); |
156 | self.newline(); |
157 | self.indent += 1; |
158 | |
159 | for method in &member.methods { |
160 | self.trait_item_fn(method); |
161 | self.word(";" ); |
162 | self.newline(); |
163 | } |
164 | |
165 | self.indent -= 1; |
166 | self.newline(); |
167 | self.word("}" ); |
168 | } |
169 | |
170 | fn rdl_constant(&mut self, member: &rdl::Constant) { |
171 | self.item_const(&member.item); |
172 | } |
173 | |
174 | fn rdl_function(&mut self, member: &rdl::Function) { |
175 | self.trait_item_fn(&member.item); |
176 | self.word(";" ); |
177 | self.newline(); |
178 | } |
179 | |
180 | fn item_const(&mut self, item: &syn::ItemConst) { |
181 | self.word("const " ); |
182 | self.ident(&item.ident); |
183 | self.word(": " ); |
184 | self.ty(&item.ty); |
185 | self.word(" = " ); |
186 | self.expr(&item.expr); |
187 | self.word(";" ); |
188 | self.newline(); |
189 | } |
190 | |
191 | fn attrs(&mut self, attrs: &[syn::Attribute]) { |
192 | for attr in attrs { |
193 | self.attr(attr); |
194 | } |
195 | } |
196 | |
197 | fn attr(&mut self, attr: &syn::Attribute) { |
198 | self.word("#[" ); |
199 | self.meta(&attr.meta); |
200 | self.word("]" ); |
201 | self.newline(); |
202 | } |
203 | |
204 | fn meta(&mut self, meta: &syn::Meta) { |
205 | match meta { |
206 | syn::Meta::Path(path) => self.path(path), |
207 | syn::Meta::List(list) => self.meta_list(list), |
208 | syn::Meta::NameValue(meta) => self.meta_name_value(meta), |
209 | } |
210 | } |
211 | |
212 | fn meta_list(&mut self, meta_list: &syn::MetaList) { |
213 | self.path(&meta_list.path); |
214 | self.word("(" ); |
215 | self.word(&meta_list.tokens.to_string()); |
216 | self.word(")" ); |
217 | } |
218 | |
219 | fn meta_name_value(&mut self, meta: &syn::MetaNameValue) { |
220 | self.path(&meta.path); |
221 | self.word(" = " ); |
222 | self.expr(&meta.value); |
223 | } |
224 | |
225 | fn rdl_struct(&mut self, member: &rdl::Struct) { |
226 | self.attrs(&member.attributes); |
227 | |
228 | self.word("struct " ); |
229 | self.word(&member.name); |
230 | self.word(" {" ); |
231 | self.newline(); |
232 | self.indent += 1; |
233 | |
234 | for field in &member.fields { |
235 | self.word(&field.name); |
236 | self.word(": " ); |
237 | self.ty(&field.ty); |
238 | self.word("," ); |
239 | self.newline(); |
240 | } |
241 | |
242 | self.indent -= 1; |
243 | self.newline(); |
244 | self.word("}" ); |
245 | } |
246 | |
247 | fn rdl_enum(&mut self, member: &rdl::Enum) { |
248 | self.attrs(&member.item.attrs); |
249 | |
250 | self.word("enum " ); |
251 | self.ident(&member.item.ident); |
252 | self.word(" {" ); |
253 | self.newline(); |
254 | self.indent += 1; |
255 | |
256 | for variant in &member.item.variants { |
257 | self.ident(&variant.ident); |
258 | if let Some((_, expr)) = &variant.discriminant { |
259 | self.word(" = " ); |
260 | self.expr(expr); |
261 | } |
262 | self.word("," ); |
263 | self.newline(); |
264 | } |
265 | |
266 | self.indent -= 1; |
267 | self.newline(); |
268 | self.word("}" ); |
269 | } |
270 | |
271 | fn trait_item_fn(&mut self, method: &syn::TraitItemFn) { |
272 | self.attrs(&method.attrs); |
273 | self.signature(&method.sig); |
274 | } |
275 | |
276 | fn signature(&mut self, signature: &syn::Signature) { |
277 | self.word("fn " ); |
278 | self.ident(&signature.ident); |
279 | self.word("(" ); |
280 | |
281 | let mut first = true; |
282 | for input in &signature.inputs { |
283 | if first { |
284 | first = false; |
285 | } else { |
286 | self.word(", " ); |
287 | } |
288 | self.fn_arg(input); |
289 | } |
290 | |
291 | self.word(")" ); |
292 | |
293 | if let syn::ReturnType::Type(_, ty) = &signature.output { |
294 | self.word(" -> " ); |
295 | self.ty(ty); |
296 | } |
297 | } |
298 | |
299 | fn fn_arg(&mut self, fn_arg: &syn::FnArg) { |
300 | if let syn::FnArg::Typed(pat_type) = fn_arg { |
301 | self.pat_type(pat_type); |
302 | } |
303 | } |
304 | |
305 | fn pat_type(&mut self, pat_type: &syn::PatType) { |
306 | self.pat(&pat_type.pat); |
307 | self.word(": " ); |
308 | self.ty(&pat_type.ty); |
309 | } |
310 | |
311 | fn pat(&mut self, pat: &syn::Pat) { |
312 | match pat { |
313 | syn::Pat::Ident(pat_ident) => self.pat_ident(pat_ident), |
314 | rest => unimplemented!(" {rest:?}" ), |
315 | } |
316 | } |
317 | |
318 | fn pat_ident(&mut self, pat_ident: &syn::PatIdent) { |
319 | self.ident(&pat_ident.ident); |
320 | } |
321 | |
322 | fn ty(&mut self, ty: &syn::Type) { |
323 | match ty { |
324 | syn::Type::Path(ty) => self.type_path(ty), |
325 | syn::Type::Ptr(ptr) => self.type_ptr(ptr), |
326 | syn::Type::Array(array) => self.type_array(array), |
327 | rest => unimplemented!(" {rest:?}" ), |
328 | } |
329 | } |
330 | |
331 | fn type_array(&mut self, array: &syn::TypeArray) { |
332 | self.word("[" ); |
333 | self.ty(&array.elem); |
334 | self.word("; " ); |
335 | self.expr(&array.len); |
336 | self.word("]" ); |
337 | } |
338 | |
339 | fn expr(&mut self, expr: &syn::Expr) { |
340 | match expr { |
341 | syn::Expr::Lit(lit) => self.expr_lit(lit), |
342 | syn::Expr::Unary(unary) => self.expr_unary(unary), |
343 | rest => unimplemented!(" {rest:?}" ), |
344 | } |
345 | } |
346 | |
347 | fn expr_unary(&mut self, unary: &syn::ExprUnary) { |
348 | self.word("-" ); |
349 | self.expr(&unary.expr); |
350 | } |
351 | |
352 | fn expr_lit(&mut self, expr: &syn::ExprLit) { |
353 | self.lit(&expr.lit); |
354 | } |
355 | |
356 | fn lit(&mut self, lit: &syn::Lit) { |
357 | match lit { |
358 | syn::Lit::Int(lit) => self.lit_int(lit), |
359 | syn::Lit::Str(lit) => self.lit_str(lit), |
360 | _ => _ = dbg!(lit), |
361 | } |
362 | } |
363 | |
364 | fn lit_str(&mut self, lit: &syn::LitStr) { |
365 | self.word(" \"" ); |
366 | self.word(&lit.value()); |
367 | self.word(" \"" ); |
368 | } |
369 | |
370 | fn lit_int(&mut self, lit: &syn::LitInt) { |
371 | self.word(&lit.token().to_string()); |
372 | } |
373 | |
374 | fn type_ptr(&mut self, ptr: &syn::TypePtr) { |
375 | if ptr.mutability.is_some() { |
376 | self.word("*mut " ); |
377 | } else { |
378 | self.word("*const " ); |
379 | } |
380 | self.ty(&ptr.elem); |
381 | } |
382 | |
383 | fn type_path(&mut self, ty: &syn::TypePath) { |
384 | self.path(&ty.path); |
385 | } |
386 | |
387 | fn path(&mut self, path: &syn::Path) { |
388 | let mut first = true; |
389 | for segment in &path.segments { |
390 | if first { |
391 | first = false; |
392 | } else { |
393 | self.word("::" ); |
394 | } |
395 | self.path_segment(segment); |
396 | } |
397 | } |
398 | |
399 | pub fn path_segment(&mut self, segment: &syn::PathSegment) { |
400 | self.ident(&segment.ident); |
401 | |
402 | if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { |
403 | self.word("<" ); |
404 | |
405 | let mut first = true; |
406 | for arg in &args.args { |
407 | if first { |
408 | first = false; |
409 | } else { |
410 | self.word(", " ); |
411 | } |
412 | self.generic_argument(arg); |
413 | } |
414 | |
415 | self.word(">" ); |
416 | } |
417 | } |
418 | |
419 | fn generic_argument(&mut self, arg: &syn::GenericArgument) { |
420 | match arg { |
421 | syn::GenericArgument::Type(ty) => self.ty(ty), |
422 | rest => unimplemented!(" {rest:?}" ), |
423 | } |
424 | } |
425 | |
426 | fn item_use(&mut self, item: &syn::ItemUse) { |
427 | self.word("use " ); |
428 | self.use_tree(&item.tree); |
429 | self.word(";" ); |
430 | self.newline(); |
431 | } |
432 | |
433 | fn use_tree(&mut self, use_tree: &syn::UseTree) { |
434 | match use_tree { |
435 | syn::UseTree::Path(use_path) => self.use_path(use_path), |
436 | syn::UseTree::Name(use_name) => self.use_name(use_name), |
437 | _ => {} |
438 | } |
439 | } |
440 | |
441 | fn use_path(&mut self, use_path: &syn::UsePath) { |
442 | self.ident(&use_path.ident); |
443 | self.word("::" ); |
444 | self.use_tree(&use_path.tree); |
445 | } |
446 | |
447 | fn use_name(&mut self, use_name: &syn::UseName) { |
448 | self.ident(&use_name.ident); |
449 | } |
450 | |
451 | pub fn ident(&mut self, ident: &syn::Ident) { |
452 | self.word(&ident.to_string()); |
453 | } |
454 | } |
455 | |